commit 3f5887f84fc15735d6201b13321e81d840ebd17b Author: CentOS Sources Date: Tue May 16 06:08:58 2023 +0000 import gnome-shell-extensions-3.32.1-33.el8 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3529e4d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/gnome-shell-extensions-3.32.1.tar.xz diff --git a/.gnome-shell-extensions.metadata b/.gnome-shell-extensions.metadata new file mode 100644 index 0000000..4e2ddcc --- /dev/null +++ b/.gnome-shell-extensions.metadata @@ -0,0 +1 @@ +51c1c16bcd0dc9125834b32d7c539c38fa9c4f52 SOURCES/gnome-shell-extensions-3.32.1.tar.xz diff --git a/SOURCES/0001-Add-gesture-inhibitor-extension.patch b/SOURCES/0001-Add-gesture-inhibitor-extension.patch new file mode 100644 index 0000000..66ce200 --- /dev/null +++ b/SOURCES/0001-Add-gesture-inhibitor-extension.patch @@ -0,0 +1,186 @@ +From 2a498fef3ec02d834346b545aeacba0a6224494e Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 28 Jan 2021 00:06:12 +0100 +Subject: [PATCH] Add gesture-inhibitor extension + +This extension may disable default GNOME Shell gestures. +--- + extensions/gesture-inhibitor/extension.js | 75 +++++++++++++++++++ + extensions/gesture-inhibitor/meson.build | 8 ++ + extensions/gesture-inhibitor/metadata.json.in | 12 +++ + ...l.extensions.gesture-inhibitor.gschema.xml | 25 +++++++ + extensions/gesture-inhibitor/stylesheet.css | 1 + + meson.build | 1 + + 6 files changed, 122 insertions(+) + create mode 100644 extensions/gesture-inhibitor/extension.js + create mode 100644 extensions/gesture-inhibitor/meson.build + create mode 100644 extensions/gesture-inhibitor/metadata.json.in + create mode 100644 extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml + create mode 100644 extensions/gesture-inhibitor/stylesheet.css + +diff --git a/extensions/gesture-inhibitor/extension.js b/extensions/gesture-inhibitor/extension.js +new file mode 100644 +index 00000000..e74ede2f +--- /dev/null ++++ b/extensions/gesture-inhibitor/extension.js +@@ -0,0 +1,75 @@ ++/* extension.js ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++/* exported init */ ++ ++const Clutter = imports.gi.Clutter; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const ViewSelector = imports.ui.viewSelector; ++const EdgeDragAction = imports.ui.edgeDragAction; ++const WindowManager = imports.ui.windowManager; ++const St = imports.gi.St; ++const Gio = imports.gi.Gio; ++ ++class Extension { ++ constructor() { ++ this._settings = ExtensionUtils.getSettings(); ++ let actions = global.stage.get_actions(); ++ ++ actions.forEach(a => { ++ if (a instanceof ViewSelector.ShowOverviewAction) ++ this._showOverview = a; ++ else if (a instanceof WindowManager.AppSwitchAction) ++ this._appSwitch = a; ++ else if (a instanceof EdgeDragAction.EdgeDragAction && ++ a._side == St.Side.BOTTOM) ++ this._showOsk = a; ++ else if (a instanceof EdgeDragAction.EdgeDragAction && ++ a._side == St.Side.TOP) ++ this._unfullscreen = a; ++ else if (a instanceof EdgeDragAction.EdgeDragAction) ++ this._showAppGrid = a; ++ }); ++ ++ this._map = [ ++ { setting: 'overview', action: this._showOverview }, ++ { setting: 'app-switch', action: this._appSwitch }, ++ { setting: 'show-osk', action: this._showOsk }, ++ { setting: 'unfullscreen', action: this._unfullscreen }, ++ { setting: 'show-app-grid', action: this._showAppGrid } ++ ]; ++ } ++ ++ enable() { ++ this._map.forEach(m => { ++ this._settings.bind(m.setting, m.action, 'enabled', ++ Gio.SettingsBindFlags.DEFAULT); ++ }); ++ } ++ ++ disable() { ++ this._map.forEach(m => { ++ m.action.enabled = true; ++ }); ++ } ++} ++ ++function init() { ++ return new Extension(); ++} +diff --git a/extensions/gesture-inhibitor/meson.build b/extensions/gesture-inhibitor/meson.build +new file mode 100644 +index 00000000..fdad5cc8 +--- /dev/null ++++ b/extensions/gesture-inhibitor/meson.build +@@ -0,0 +1,8 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++# extension_sources += files('prefs.js') ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') +diff --git a/extensions/gesture-inhibitor/metadata.json.in b/extensions/gesture-inhibitor/metadata.json.in +new file mode 100644 +index 00000000..37d6a117 +--- /dev/null ++++ b/extensions/gesture-inhibitor/metadata.json.in +@@ -0,0 +1,12 @@ ++{ ++ "uuid": "@uuid@", ++ "extension-id": "@extension_id@", ++ "settings-schema": "@gschemaname@", ++ "gettext-domain": "@gettext_domain@", ++ "name": "Gesture Inhibitor", ++ "description": "Makes touchscreen gestures optional.", ++ "shell-version": [ "@shell_current@" ], ++ "original-authors": [ "cgarnach@redhat.com" ], ++ "url": "@url@" ++} ++ +diff --git a/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml b/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml +new file mode 100644 +index 00000000..1d67dcc0 +--- /dev/null ++++ b/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml +@@ -0,0 +1,25 @@ ++ ++ ++ ++ true ++ Show app grid gesture ++ ++ ++ true ++ Show OSK gesture ++ ++ ++ true ++ Show Overview gesture ++ ++ ++ true ++ Application switch gesture ++ ++ ++ true ++ Unfullscreen gesture ++ ++ ++ ++ +diff --git a/extensions/gesture-inhibitor/stylesheet.css b/extensions/gesture-inhibitor/stylesheet.css +new file mode 100644 +index 00000000..37b93f21 +--- /dev/null ++++ b/extensions/gesture-inhibitor/stylesheet.css +@@ -0,0 +1 @@ ++/* Add your custom extension styling here */ +diff --git a/meson.build b/meson.build +index e163b84d..ba84f8f3 100644 +--- a/meson.build ++++ b/meson.build +@@ -55,6 +55,7 @@ all_extensions += [ + 'dash-to-dock', + 'dash-to-panel', + 'disable-screenshield', ++ 'gesture-inhibitor', + 'native-window-placement', + 'no-hot-corner', + 'panel-favorites', +-- +2.32.0 + diff --git a/SOURCES/0001-Include-top-icons-in-classic-session.patch b/SOURCES/0001-Include-top-icons-in-classic-session.patch new file mode 100644 index 0000000..9c5283f --- /dev/null +++ b/SOURCES/0001-Include-top-icons-in-classic-session.patch @@ -0,0 +1,32 @@ +From a3db60786407481efbfc4875f887d03b58f0a7b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 23 Feb 2018 16:56:46 +0100 +Subject: [PATCH] Include top-icons in classic session + +--- + meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index 6764f9a..32743ed 100644 +--- a/meson.build ++++ b/meson.build +@@ -36,6 +36,7 @@ classic_extensions = [ + 'desktop-icons', + 'places-menu', + 'launch-new-instance', ++ 'top-icons', + 'window-list' + ] + +@@ -56,7 +57,6 @@ all_extensions += [ + 'no-hot-corner', + 'panel-favorites', + 'systemMonitor', +- 'top-icons', + 'updates-dialog', + 'user-theme', + 'window-grouper' +-- +2.21.0 + diff --git a/SOURCES/0001-Update-desktop-icons-gettext-domain.patch b/SOURCES/0001-Update-desktop-icons-gettext-domain.patch new file mode 100644 index 0000000..454989d --- /dev/null +++ b/SOURCES/0001-Update-desktop-icons-gettext-domain.patch @@ -0,0 +1,83 @@ +From f5e47cd8ca32ae433f6906b01a509c5a304894d9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sat, 24 Oct 2020 01:14:44 +0200 +Subject: [PATCH] Update desktop-icons gettext domain + +--- + extensions/desktop-icons/createFolderDialog.js | 2 +- + extensions/desktop-icons/desktopGrid.js | 2 +- + extensions/desktop-icons/fileItem.js | 2 +- + extensions/desktop-icons/prefs.js | 8 +++++--- + 4 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/extensions/desktop-icons/createFolderDialog.js b/extensions/desktop-icons/createFolderDialog.js +index f3e40e9..5038762 100644 +--- a/extensions/desktop-icons/createFolderDialog.js ++++ b/extensions/desktop-icons/createFolderDialog.js +@@ -21,7 +21,7 @@ const { Clutter, GObject, GLib, Gio, St } = imports.gi; + const Signals = imports.signals; + + const Dialog = imports.ui.dialog; +-const Gettext = imports.gettext.domain('desktop-icons'); ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const ModalDialog = imports.ui.modalDialog; + const ShellEntry = imports.ui.shellEntry; + const Tweener = imports.ui.tweener; +diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js +index a2d1f12..94d2dfd 100644 +--- a/extensions/desktop-icons/desktopGrid.js ++++ b/extensions/desktop-icons/desktopGrid.js +@@ -44,7 +44,7 @@ const Util = imports.misc.util; + + const Clipboard = St.Clipboard.get_default(); + const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; +-const Gettext = imports.gettext.domain('desktop-icons'); ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); + + const _ = Gettext.gettext; + +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index 0c6a54d..d6d43c9 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -42,7 +42,7 @@ const Prefs = Me.imports.prefs; + const DBusUtils = Me.imports.dbusUtils; + const DesktopIconsUtil = Me.imports.desktopIconsUtil; + +-const Gettext = imports.gettext.domain('desktop-icons'); ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); + + const _ = Gettext.gettext; + +diff --git a/extensions/desktop-icons/prefs.js b/extensions/desktop-icons/prefs.js +index 4b8d986..51daf15 100644 +--- a/extensions/desktop-icons/prefs.js ++++ b/extensions/desktop-icons/prefs.js +@@ -26,7 +26,7 @@ const Gettext = imports.gettext; + + const Config = imports.misc.config; + +-var _ = Gettext.domain('desktop-icons').gettext; ++var _ = Gettext.domain('gnome-shell-extensions').gettext; + + const SCHEMA_NAUTILUS = 'org.gnome.nautilus.preferences'; + const SCHEMA_GTK = 'org.gtk.Settings.FileChooser'; +@@ -51,11 +51,13 @@ var CLICK_POLICY_SINGLE = false; + function initTranslations() { + let extension = ExtensionUtils.getCurrentExtension(); + ++ let domain = extension.metadata['gettext-domain'] || 'desktop-icons'; ++ + let localedir = extension.dir.get_child('locale'); + if (localedir.query_exists(null)) +- Gettext.bindtextdomain('desktop-icons', localedir.get_path()); ++ Gettext.bindtextdomain(domain, localedir.get_path()); + else +- Gettext.bindtextdomain('desktop-icons', Config.LOCALEDIR); ++ Gettext.bindtextdomain(domain, Config.LOCALEDIR); + } + + function init() { +-- +2.21.1 + diff --git a/SOURCES/0001-Update-style.patch b/SOURCES/0001-Update-style.patch new file mode 100644 index 0000000..8173ded --- /dev/null +++ b/SOURCES/0001-Update-style.patch @@ -0,0 +1,98 @@ +From e768ad73e2d68b3f1567051675ba0539a75e3105 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sat, 18 May 2019 19:37:05 +0200 +Subject: [PATCH] Update style + +--- + data/gnome-shell-sass | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Submodule data/gnome-shell-sass 1a56956..8842e57: +diff --git a/data/gnome-shell-sass/_common.scss b/data/gnome-shell-sass/_common.scss +index a6357ba..62d9c82 100644 +--- a/data/gnome-shell-sass/_common.scss ++++ b/data/gnome-shell-sass/_common.scss +@@ -571,6 +571,18 @@ StScrollBar { + app menu inside the main app window itself rather than the top bar + */ + ++/************* ++ * App Icons * ++ *************/ ++/* Outline for low res icons */ ++.lowres-icon { ++ icon-shadow: 0 1px 2px rgba(0,0,0,0.3); ++} ++ ++/* Drapshadow for large icons */ ++.icon-dropshadow { ++ icon-shadow: 0 1px 2px rgba(0,0,0,0.4); ++} + + /* OSD */ + .osd-window { +@@ -680,7 +692,8 @@ StScrollBar { + spacing: 8px; + } + +- .ws-switcher-active-up, .ws-switcher-active-down { ++ .ws-switcher-active-up, .ws-switcher-active-down, ++ .ws-switcher-active-left, .ws-switcher-active-right { + height: 50px; + background-color: $selected_bg_color; + color: $selected_fg_color; +@@ -781,6 +794,11 @@ StScrollBar { + color: lighten($fg_color,10%); + } + ++ .panel-logo-icon { ++ padding-right: .4em; ++ icon-size: 1em; ++ } ++ + .system-status-icon { icon-size: 1.09em; padding: 0 5px; } + .unlock-screen &, + .login-screen &, +@@ -1406,6 +1424,14 @@ StScrollBar { + + } + ++ .app-well-hover-text { ++ text-align: center; ++ color: $osd_fg_color; ++ background-color: $osd_bg_color; ++ border-radius: 5px; ++ padding: 3px; ++ } ++ + .app-well-app-running-dot { //running apps indicator + width: 10px; height: 3px; + background-color: $selected_bg_color; +@@ -1801,7 +1827,12 @@ StScrollBar { + .login-dialog-banner { color: darken($osd_fg_color,10%); } + .login-dialog-button-box { spacing: 5px; } + .login-dialog-message-warning { color: $warning_color; } +- .login-dialog-message-hint { padding-top: 0; padding-bottom: 20px; } ++ .login-dialog-message-hint, .login-dialog-message { ++ color: darken($osd_fg_color, 20%); ++ padding-top: 0; ++ padding-bottom: 20px; ++ min-height: 2.75em; ++ } + .login-dialog-user-selection-box { padding: 100px 0px; } + .login-dialog-not-listed-label { + padding-left: 2px; +@@ -1856,6 +1887,10 @@ StScrollBar { + padding-bottom: 12px; + spacing: 8px; + width: 23em; ++ .login-dialog-timed-login-indicator { ++ height: 2px; ++ background-color: darken($fg_color,40%); ++ } + } + + .login-dialog-prompt-label { +-- +2.21.0 + diff --git a/SOURCES/0001-apps-menu-Add-missing-chain-up.patch b/SOURCES/0001-apps-menu-Add-missing-chain-up.patch new file mode 100644 index 0000000..35fd0f7 --- /dev/null +++ b/SOURCES/0001-apps-menu-Add-missing-chain-up.patch @@ -0,0 +1,33 @@ +From 0bbeadadc41128b2be1f2b56c60b5a7a671d40da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 27 Jun 2019 03:57:53 +0200 +Subject: [PATCH] apps-menu: Add missing chain-up + +PanelMenu.Button is a bit weird in that it also "contains" its parent +actor. That container is supposed to be destroyed with the button, but +as we currently don't chain up to the parent class' _onDestroy(), we +leave behind an empty container every time the extension is disabled. + +Fix this by adding the missing chain-up. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/75 +--- + extensions/apps-menu/extension.js | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index b9e7111..9803cc1 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -433,6 +433,8 @@ class ApplicationsButton extends PanelMenu.Button { + } + + _onDestroy() { ++ super._onDestroy(); ++ + Main.overview.disconnect(this._showingId); + Main.overview.disconnect(this._hidingId); + appSys.disconnect(this._installedChangedId); +-- +2.21.0 + diff --git a/SOURCES/0001-apps-menu-Explicitly-set-label_actor.patch b/SOURCES/0001-apps-menu-Explicitly-set-label_actor.patch new file mode 100644 index 0000000..131ea79 --- /dev/null +++ b/SOURCES/0001-apps-menu-Explicitly-set-label_actor.patch @@ -0,0 +1,40 @@ +From 52ee25effa3debb21307e33ac223cf48ac7bc57a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 17 Mar 2016 17:15:38 +0100 +Subject: [PATCH] apps-menu: Explicitly set label_actor + +For some reason orca fails to pick up the label of category items, +so set the label_actor explicitly as workaround. +--- + extensions/apps-menu/extension.js | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index d62e3d7..cc399c6 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -29,7 +29,9 @@ class ActivitiesMenuItem extends PopupMenu.PopupBaseMenuItem { + constructor(button) { + super(); + this._button = button; +- this.actor.add_child(new St.Label({ text: _('Activities Overview') })); ++ let label = new St.Label({ text: _('Activities Overview') }); ++ this.actor.add_child(label); ++ this.actor.label_actor = label; + } + + activate(event) { +@@ -120,7 +122,9 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { + else + name = _('Favorites'); + +- this.actor.add_child(new St.Label({ text: name })); ++ let label = new St.Label({ text: name }); ++ this.actor.add_child(label); ++ this.actor.label_actor = label; + this.actor.connect('motion-event', this._onMotionEvent.bind(this)); + } + +-- +2.21.0 + diff --git a/SOURCES/0001-apps-menu-add-logo-icon-to-Applications-menu.patch b/SOURCES/0001-apps-menu-add-logo-icon-to-Applications-menu.patch new file mode 100644 index 0000000..973c077 --- /dev/null +++ b/SOURCES/0001-apps-menu-add-logo-icon-to-Applications-menu.patch @@ -0,0 +1,32 @@ +From 3e3634b59455da0cbae1de4af0ce5cf97be8b80d Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 21 Jan 2014 16:48:17 -0500 +Subject: [PATCH] apps-menu: add logo icon to Applications menu + +Brand requested it. +--- + extensions/apps-menu/extension.js | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index d7ba570..d62e3d7 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -390,6 +390,14 @@ class ApplicationsButton extends PanelMenu.Button { + + let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' }); + ++ let iconFile = Gio.File.new_for_path( ++ '/usr/share/icons/hicolor/scalable/apps/start-here.svg'); ++ this._icon = new St.Icon({ ++ gicon: new Gio.FileIcon({ file: iconFile }), ++ style_class: 'panel-logo-icon' ++ }); ++ hbox.add_actor(this._icon); ++ + this._label = new St.Label({ + text: _('Applications'), + y_expand: true, +-- +2.21.0 + diff --git a/SOURCES/0001-auto-move-windows-Don-t-move-windows-already-on-all-.patch b/SOURCES/0001-auto-move-windows-Don-t-move-windows-already-on-all-.patch new file mode 100644 index 0000000..665227c --- /dev/null +++ b/SOURCES/0001-auto-move-windows-Don-t-move-windows-already-on-all-.patch @@ -0,0 +1,33 @@ +From 8a5e793b3d984f3acc378cf8914410311e9dde0e Mon Sep 17 00:00:00 2001 +From: Daniel van Vugt +Date: Thu, 28 Jan 2021 16:33:50 +0800 +Subject: [PATCH] auto-move-windows: Don't move windows already on all + workspaces + +This fixes a particular case of mutter#992. + +Although gnome-shell will also be softened to not crash in future, it's +also a good idea for the extension to explicitly decide how it wants to +handle windows that are already on all workspaces. + +Part-of: +--- + extensions/auto-move-windows/extension.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/auto-move-windows/extension.js b/extensions/auto-move-windows/extension.js +index b9bc3a0..3859809 100644 +--- a/extensions/auto-move-windows/extension.js ++++ b/extensions/auto-move-windows/extension.js +@@ -72,7 +72,7 @@ class WindowMover { + } + + _moveWindow(window, workspaceNum) { +- if (window.skip_taskbar) ++ if (window.skip_taskbar || window.is_on_all_workspaces()) + return; + + // ensure we have the required number of workspaces +-- +2.37.1 + diff --git a/SOURCES/0001-classification-banner-Handle-fullscreen-monitors.patch b/SOURCES/0001-classification-banner-Handle-fullscreen-monitors.patch new file mode 100644 index 0000000..e6f8315 --- /dev/null +++ b/SOURCES/0001-classification-banner-Handle-fullscreen-monitors.patch @@ -0,0 +1,68 @@ +From 3d32ab1848011a3a7af97255307b3541a7553b09 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 14 Dec 2022 16:55:51 +0100 +Subject: [PATCH] classification-banner: Handle fullscreen monitors + +When a monitor is in fullscreen, we don't want its classification +banner to be offset by an imaginary panel, but at the top of the +screen. +--- + extensions/classification-banner/extension.js | 22 +++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/extensions/classification-banner/extension.js b/extensions/classification-banner/extension.js +index 6c2fe007..1cf03b3f 100644 +--- a/extensions/classification-banner/extension.js ++++ b/extensions/classification-banner/extension.js +@@ -27,16 +27,19 @@ const Main = imports.ui.main; + const ClassificationBanner = GObject.registerClass( + class ClassificationBanner extends Clutter.Actor { + _init(index) { ++ const constraint = new Layout.MonitorConstraint({index}); + super._init({ + layout_manager: new Clutter.BinLayout(), +- constraints: new Layout.MonitorConstraint({ +- work_area: true, +- index, +- }), ++ constraints: constraint, + }); ++ this._monitorConstraint = constraint; + + this._settings = ExtensionUtils.getSettings(); + this.connect('destroy', () => { ++ if (this._fullscreenChangedId) ++ global.display.disconnect(this._fullscreenChangedId); ++ delete this._fullscreenChangedId; ++ + if (this._settings) + this._settings.run_dispose(); + this._settings = null; +@@ -95,6 +98,11 @@ class ClassificationBanner extends Clutter.Actor { + userLabel, 'visible', + Gio.SettingsBindFlags.GET); + ++ this._fullscreenChangedId = ++ global.display.connect('in-fullscreen-changed', ++ () => this._updateMonitorConstraint()); ++ this._updateMonitorConstraint(); ++ + this._settings.connect('changed::color', + () => this._updateStyles()); + this._settings.connect('changed::background-color', +@@ -111,6 +119,12 @@ class ClassificationBanner extends Clutter.Actor { + return `${key}: rgba(${red},${green},${blue},${alpha / 255});`; + } + ++ _updateMonitorConstraint() { ++ const {index} = this._monitorConstraint; ++ this._monitorConstraint.work_area = ++ !global.display.get_monitor_in_fullscreen(index); ++ } ++ + _updateStyles() { + const bgStyle = this._getColorSetting('background-color'); + const fgStyle = this._getColorSetting('color'); +-- +2.38.1 + diff --git a/SOURCES/0001-dashToDock-Handle-no-overview-case.patch b/SOURCES/0001-dashToDock-Handle-no-overview-case.patch new file mode 100644 index 0000000..e7a2cdc --- /dev/null +++ b/SOURCES/0001-dashToDock-Handle-no-overview-case.patch @@ -0,0 +1,208 @@ +From 3c62051c0a154ae987bb0126e8adb6cd86aa69a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 24 Feb 2020 16:17:05 +0100 +Subject: [PATCH] dashToDock: Handle no-overview case + +There is no longer an overview in GNOME Classic, so in order to be +used in that environment, the extension must deal with that case. +--- + extensions/dash-to-dock/docking.js | 122 ++++++++++++++++------------- + 1 file changed, 68 insertions(+), 54 deletions(-) + +diff --git a/extensions/dash-to-dock/docking.js b/extensions/dash-to-dock/docking.js +index d35094b..2b8353a 100644 +--- a/extensions/dash-to-dock/docking.js ++++ b/extensions/dash-to-dock/docking.js +@@ -233,7 +233,7 @@ var DockedDash = class DashToDock { + // Create a new dash object + this.dash = new MyDash.MyDash(this._settings, this._remoteModel, this._monitorIndex); + +- if (!this._settings.get_boolean('show-show-apps-button')) ++ if (Main.overview.isDummy || !this._settings.get_boolean('show-show-apps-button')) + this.dash.hideShowAppsButton(); + + // Create the main actor and the containers for sliding in and out and +@@ -272,45 +272,11 @@ var DockedDash = class DashToDock { + this.dash.actor.add_constraint(this.constrainSize); + + this._signalsHandler.add([ +- Main.overview, +- 'item-drag-begin', +- this._onDragStart.bind(this) +- ], [ +- Main.overview, +- 'item-drag-end', +- this._onDragEnd.bind(this) +- ], [ +- Main.overview, +- 'item-drag-cancelled', +- this._onDragEnd.bind(this) +- ], [ + // update when workarea changes, for instance if other extensions modify the struts + //(like moving th panel at the bottom) + global.display, + 'workareas-changed', + this._resetPosition.bind(this) +- ], [ +- Main.overview, +- 'showing', +- this._onOverviewShowing.bind(this) +- ], [ +- Main.overview, +- 'hiding', +- this._onOverviewHiding.bind(this) +- ], [ +- // Hide on appview +- Main.overview.viewSelector, +- 'page-changed', +- this._pageChanged.bind(this) +- ], [ +- Main.overview.viewSelector, +- 'page-empty', +- this._onPageEmpty.bind(this) +- ], [ +- // Ensure the ShowAppsButton status is kept in sync +- Main.overview.viewSelector._showAppsButton, +- 'notify::checked', +- this._syncShowAppsButtonToggled.bind(this) + ], [ + global.display, + 'in-fullscreen-changed', +@@ -325,15 +291,6 @@ var DockedDash = class DashToDock { + this.dash, + 'icon-size-changed', + () => { Main.overview.dashIconSize = this.dash.iconSize; } +- ], [ +- // This duplicate the similar signal which is in owerview.js. +- // Being connected and thus executed later this effectively +- // overwrite any attempt to use the size of the default dash +- //which given the customization is usually much smaller. +- // I can't easily disconnect the original signal +- Main.overview._controls.dash, +- 'icon-size-changed', +- () => { Main.overview.dashIconSize = this.dash.iconSize; } + ], [ + // sync hover after a popupmenu is closed + this.dash, +@@ -341,6 +298,53 @@ var DockedDash = class DashToDock { + () => { this._box.sync_hover() } + ]); + ++ if (!Main.overview.isDummy) { ++ this._signalsHandler.add([ ++ Main.overview, ++ 'item-drag-begin', ++ this._onDragStart.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-end', ++ this._onDragEnd.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-cancelled', ++ this._onDragEnd.bind(this) ++ ], [ ++ Main.overview, ++ 'showing', ++ this._onOverviewShowing.bind(this) ++ ], [ ++ Main.overview, ++ 'hiding', ++ this._onOverviewHiding.bind(this) ++ ], [ ++ // Hide on appview ++ Main.overview.viewSelector, ++ 'page-changed', ++ this._pageChanged.bind(this) ++ ], [ ++ Main.overview.viewSelector, ++ 'page-empty', ++ this._onPageEmpty.bind(this) ++ ], [ ++ // Ensure the ShowAppsButton status is kept in sync ++ Main.overview.viewSelector._showAppsButton, ++ 'notify::checked', ++ this._syncShowAppsButtonToggled.bind(this) ++ ], [ ++ // This duplicate the similar signal which is in owerview.js. ++ // Being connected and thus executed later this effectively ++ // overwrite any attempt to use the size of the default dash ++ //which given the customization is usually much smaller. ++ // I can't easily disconnect the original signal ++ Main.overview._controls.dash, ++ 'icon-size-changed', ++ () => { Main.overview.dashIconSize = this.dash.iconSize; } ++ ]); ++ } ++ + this._injectionsHandler = new Utils.InjectionsHandler(); + this._themeManager = new Theming.ThemeManager(this._settings, this); + +@@ -370,14 +374,17 @@ var DockedDash = class DashToDock { + this._dashSpacer = new OverviewControls.DashSpacer(); + this._dashSpacer.setDashActor(this._box); + +- if (this._position == St.Side.LEFT) +- Main.overview._controls._group.insert_child_at_index(this._dashSpacer, this._rtl ? -1 : 0); // insert on first +- else if (this._position == St.Side.RIGHT) +- Main.overview._controls._group.insert_child_at_index(this._dashSpacer, this._rtl ? 0 : -1); // insert on last +- else if (this._position == St.Side.TOP) +- Main.overview._overview.insert_child_at_index(this._dashSpacer, 0); +- else if (this._position == St.Side.BOTTOM) +- Main.overview._overview.insert_child_at_index(this._dashSpacer, -1); ++ if (!Main.overview.isDummy) { ++ const { _controls, _overview } = Main.overview; ++ if (this._position == St.Side.LEFT) ++ _controls._group.insert_child_at_index(this._dashSpacer, this._rtl ? -1 : 0); // insert on first ++ else if (this._position == St.Side.RIGHT) ++ _controls._group.insert_child_at_index(this._dashSpacer, this._rtl ? 0 : -1); // insert on last ++ else if (this._position == St.Side.TOP) ++ _overview.insert_child_at_index(this._dashSpacer, 0); ++ else if (this._position == St.Side.BOTTOM) ++ _overview.insert_child_at_index(this._dashSpacer, -1); ++ } + + // Add dash container actor and the container to the Chrome. + this.actor.set_child(this._slider); +@@ -412,7 +419,7 @@ var DockedDash = class DashToDock { + + // Since Gnome 3.8 dragging an app without having opened the overview before cause the attemp to + //animate a null target since some variables are not initialized when the viewSelector is created +- if (Main.overview.viewSelector._activePage == null) ++ if (!Main.overview.isDummy && Main.overview.viewSelector._activePage == null) + Main.overview.viewSelector._activePage = Main.overview.viewSelector._workspacesPage; + + this._updateVisibilityMode(); +@@ -493,7 +500,8 @@ var DockedDash = class DashToDock { + this._settings, + 'changed::show-show-apps-button', + () => { +- if (this._settings.get_boolean('show-show-apps-button')) ++ if (!Main.overview.isDummy && ++ this._settings.get_boolean('show-show-apps-button')) + this.dash.showShowAppsButton(); + else + this.dash.hideShowAppsButton(); +@@ -1681,6 +1689,9 @@ var DockManager = class DashToDock_DockManager { + // set stored icon size to the new dash + Main.overview.dashIconSize = this._allDocks[0].dash.iconSize; + ++ if (Main.overview.isDummy) ++ return; ++ + // Hide usual Dash + Main.overview._controls.dash.actor.hide(); + +@@ -1707,6 +1718,9 @@ var DockManager = class DashToDock_DockManager { + } + + _restoreDash() { ++ if (Main.overview.isDummy) ++ return; ++ + Main.overview._controls.dash.actor.show(); + Main.overview._controls.dash.actor.set_width(-1); //reset default dash size + // This force the recalculation of the icon size +-- +2.25.0 + diff --git a/SOURCES/0001-desktop-icons-Don-t-use-blocking-IO.patch b/SOURCES/0001-desktop-icons-Don-t-use-blocking-IO.patch new file mode 100644 index 0000000..0224a30 --- /dev/null +++ b/SOURCES/0001-desktop-icons-Don-t-use-blocking-IO.patch @@ -0,0 +1,76 @@ +From 93e3e938b322433aff862bbc46f80c60ab7dc2ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 17 Jan 2023 20:31:21 +0100 +Subject: [PATCH] desktop-icons: Don't use blocking IO + +--- + extensions/desktop-icons/desktopManager.js | 35 +++++++++++++++++----- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/extensions/desktop-icons/desktopManager.js b/extensions/desktop-icons/desktopManager.js +index 399aee03..2ce6eefb 100644 +--- a/extensions/desktop-icons/desktopManager.js ++++ b/extensions/desktop-icons/desktopManager.js +@@ -53,6 +53,21 @@ function findMonitorIndexForPos(x, y) { + return getDpy().get_monitor_index_for_rect(new Meta.Rectangle({x, y})); + } + ++async function queryInfo(file, attributes = DesktopIconsUtil.DEFAULT_ATTRIBUTES, cancellable = null) { ++ const flags = Gio.FileQueryInfoFlags.NONE; ++ const priority = GLib.PRIORITY_DEFAULT; ++ return new Promise((resolve, reject) => { ++ file.query_info_async(attributes, flags, priority, cancellable, (o, res) => { ++ try { ++ const info = file.query_info_finish(res); ++ resolve(info); ++ } catch (e) { ++ reject(e); ++ } ++ }); ++ }); ++} ++ + + var DesktopManager = GObject.registerClass({ + Properties: { +@@ -221,9 +236,7 @@ var DesktopManager = GObject.registerClass({ + + if (!this._unixMode) { + let desktopDir = DesktopIconsUtil.getDesktopDir(); +- let fileInfo = desktopDir.query_info(Gio.FILE_ATTRIBUTE_UNIX_MODE, +- Gio.FileQueryInfoFlags.NONE, +- null); ++ let fileInfo = await queryInfo(desktopDir, Gio.FILE_ATTRIBUTE_UNIX_MODE); + this._unixMode = fileInfo.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE); + this._setWritableByOthers((this._unixMode & S_IWOTH) != 0); + } +@@ -268,14 +281,22 @@ var DesktopManager = GObject.registerClass({ + Gio.FileQueryInfoFlags.NONE, + GLib.PRIORITY_DEFAULT, + this._desktopEnumerateCancellable, +- (source, result) => { ++ async (source, result) => { + try { + let fileEnum = source.enumerate_children_finish(result); ++ let extraFolders = await Promise.all(DesktopIconsUtil.getExtraFolders() ++ .map(async ([folder, extras]) => { ++ const info = await queryInfo(folder, ++ DesktopIconsUtil.DEFAULT_ATTRIBUTES, ++ this._desktopEnumerateCancellable); ++ return [folder, info, extras]; ++ })); ++ + let resultGenerator = function *() { ++ for (let [newFolder, info, extras] of extraFolders) ++ yield [newFolder, info, extras]; ++ + let info; +- for (let [newFolder, extras] of DesktopIconsUtil.getExtraFolders()) { +- yield [newFolder, newFolder.query_info(DesktopIconsUtil.DEFAULT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, this._desktopEnumerateCancellable), extras]; +- } + while ((info = fileEnum.next_file(null))) + yield [fileEnum.get_child(info), info, Prefs.FileType.NONE]; + }.bind(this); +-- +2.38.1 + diff --git a/SOURCES/0001-desktop-icons-Fix-stuck-grab-issue-with-rubber-bandi.patch b/SOURCES/0001-desktop-icons-Fix-stuck-grab-issue-with-rubber-bandi.patch new file mode 100644 index 0000000..73b8f24 --- /dev/null +++ b/SOURCES/0001-desktop-icons-Fix-stuck-grab-issue-with-rubber-bandi.patch @@ -0,0 +1,179 @@ +From b334c8c248f849be996963cdafb1b0b69476bdf1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 2 Nov 2021 09:20:11 +0100 +Subject: [PATCH] desktop-icons: Fix stuck grab issue with rubber banding + +The desktop icons extension can get into a state where the desktop no longer +takes mouse input. + +This happens if a user starts a rubber banding operation and then drags +the mouse to somewhere on screen that has a pop up menu, and then pops +the menu up. + +This commit addresses the bug by limiting the grab actor to the +backgrounds, and by explicitly ending the rubber banding operation +when one of the icons own menus is shown. + +One side effect of limiting the grab actor to the backgrounds, is the +rubber banding code never gets to see motion outside of the backgrounds +anymore. In order to keep drag operations feeling fluid when the user moves +toward the edge of the screen, this commit also overrides the +grab helpers captured-event handler so those motion events keep coming. + +We also start to end the rubber band if for any reason the grab it had +was released. +--- + extensions/desktop-icons/desktopGrid.js | 1 + + extensions/desktop-icons/desktopManager.js | 75 ++++++++++++++-------- + extensions/desktop-icons/fileItem.js | 1 + + 3 files changed, 49 insertions(+), 28 deletions(-) + +diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js +index 602fa7f..bd27e2a 100644 +--- a/extensions/desktop-icons/desktopGrid.js ++++ b/extensions/desktop-icons/desktopGrid.js +@@ -365,6 +365,7 @@ var DesktopGrid = class { + } + + _openMenu(x, y) { ++ Extension.desktopManager.endRubberBand(); + Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); + this.actor._desktopBackgroundMenu.open(BoxPointer.PopupAnimation.NONE); + /* Since the handler is in the press event it needs to ignore the release event +diff --git a/extensions/desktop-icons/desktopManager.js b/extensions/desktop-icons/desktopManager.js +index a70cd98..c37e1e7 100644 +--- a/extensions/desktop-icons/desktopManager.js ++++ b/extensions/desktop-icons/desktopManager.js +@@ -79,6 +79,7 @@ var DesktopManager = GObject.registerClass({ + this._queryFileInfoCancellable = null; + this._unixMode = null; + this._writableByOthers = null; ++ this._rubberBandActive = false; + + this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => this._recreateDesktopIcons()); + this._rubberBand = new St.Widget({ style_class: 'rubber-band' }); +@@ -86,6 +87,20 @@ var DesktopManager = GObject.registerClass({ + Main.layoutManager._backgroundGroup.add_child(this._rubberBand); + this._grabHelper = new GrabHelper.GrabHelper(global.stage); + ++ let origCapturedEvent = this._grabHelper.onCapturedEvent; ++ this._grabHelper.onCapturedEvent = (event) => { ++ if (event.type() === Clutter.EventType.MOTION) { ++ /* We handle motion events from a captured event handler so we ++ * we can see motion over actors that are on other parts of the ++ * stage. ++ */ ++ this._handleMotion(event); ++ return Clutter.EVENT_STOP; ++ } ++ ++ return origCapturedEvent.bind(this._grabHelper)(event); ++ }; ++ + this._addDesktopIcons(); + this._monitorDesktopFolder(); + +@@ -108,30 +123,15 @@ var DesktopManager = GObject.registerClass({ + this._initRubberBandColor(); + this._updateRubberBand(x, y); + this._rubberBand.show(); +- this._grabHelper.grab({ actor: global.stage }); ++ this._rubberBandActive = true; ++ this._grabHelper.grab({ ++ actor: Main.layoutManager._backgroundGroup, ++ onUngrab: () => this.endRubberBand(false), ++ }); + Extension.lockActivitiesButton = true; + this._stageReleaseEventId = global.stage.connect('button-release-event', (actor, event) => { + this.endRubberBand(); + }); +- this._rubberBandId = global.stage.connect('motion-event', (actor, event) => { +- /* In some cases, when the user starts a rubberband selection and ends it +- * (by releasing the left button) over a window instead of doing it over +- * the desktop, the stage doesn't receive the "button-release" event. +- * This happens currently with, at least, Dash to Dock extension, but +- * it probably also happens with other applications or extensions. +- * To fix this, we also end the rubberband selection if we detect mouse +- * motion in the stage without the left button pressed during a +- * rubberband selection. +- * */ +- let button = event.get_state(); +- if (!(button & Clutter.ModifierType.BUTTON1_MASK)) { +- this.endRubberBand(); +- return; +- } +- [x, y] = event.get_coords(); +- this._updateRubberBand(x, y); +- this._updateSelection(x, y); +- }); + this._rubberBandTouchId = global.stage.connect('touch-event', (actor, event) => { + // Let x11 pointer emulation do the job on X11 + if (!Meta.is_wayland_compositor()) +@@ -175,14 +175,37 @@ var DesktopManager = GObject.registerClass({ + } + } + +- endRubberBand() { ++ _handleMotion(event) { ++ /* In some cases, when the user starts a rubberband selection and ends it ++ * (by releasing the left button) over a window instead of doing it over ++ * the desktop, the stage doesn't receive the "button-release" event. ++ * This happens currently with, at least, Dash to Dock extension, but ++ * it probably also happens with other applications or extensions. ++ * To fix this, we also end the rubberband selection if we detect mouse ++ * motion in the stage without the left button pressed during a ++ * rubberband selection. ++ * */ ++ let button = event.get_state(); ++ if (!(button & Clutter.ModifierType.BUTTON1_MASK)) { ++ this.endRubberBand(); ++ return; ++ } ++ let [x, y] = event.get_coords(); ++ this._updateRubberBand(x, y); ++ this._updateSelection(x, y); ++ } ++ ++ endRubberBand(ungrab=true) { ++ if (!this._rubberBandActive) ++ return; ++ ++ this._rubberBandActive = false; + this._rubberBand.hide(); + Extension.lockActivitiesButton = false; +- this._grabHelper.ungrab(); +- global.stage.disconnect(this._rubberBandId); ++ if (ungrab) ++ this._grabHelper.ungrab(); + global.stage.disconnect(this._rubberBandTouchId); + global.stage.disconnect(this._stageReleaseEventId); +- this._rubberBandId = 0; + this._rubberBandTouchId = 0; + this._stageReleaseEventId = 0; + +@@ -760,10 +783,6 @@ var DesktopManager = GObject.registerClass({ + global.stage.disconnect(this._stageReleaseEventId); + this._stageReleaseEventId = 0; + +- if (this._rubberBandId) +- global.stage.disconnect(this._rubberBandId); +- this._rubberBandId = 0; +- + if (this._rubberBandTouchId) + global.stage.disconnect(this._rubberBandTouchId); + this._rubberBandTouchId = 0; +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index 1cb47e8..90f326d 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -676,6 +676,7 @@ var FileItem = class { + } + + _onPressButton(actor, event) { ++ Extension.desktopManager.endRubberBand(); + this._updateClickState(event); + let button = this._eventButton(event); + if (button == 3) { +-- +2.31.1 + diff --git a/SOURCES/0001-desktop-icons-Update-Japanese-translation.patch b/SOURCES/0001-desktop-icons-Update-Japanese-translation.patch new file mode 100644 index 0000000..43b3826 --- /dev/null +++ b/SOURCES/0001-desktop-icons-Update-Japanese-translation.patch @@ -0,0 +1,31 @@ +From 0a7248c75c084a83852aa3d0e7a36ccebd365b81 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 27 Jan 2021 11:51:28 +0100 +Subject: [PATCH] desktop-icons: Update Japanese translation + +--- + po/ja.po | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/po/ja.po b/po/ja.po +index df5646d..4d780b9 100644 +--- a/po/ja.po ++++ b/po/ja.po +@@ -293,13 +293,8 @@ msgid "Workspace %d" + msgstr "ワークスペース %d" + + #: desktopGrid.js:334 +-#, fuzzy + msgid "Display Settings" +-msgstr "" +-"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" +-"ディスプレイ設定\n" +-"#-#-#-#-# ja.po (desktop-icons master) #-#-#-#-#\n" +-"ディスプレイの設定" ++msgstr "ディスプレイ設定" + + #: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 + #, fuzzy +-- +2.29.2 + diff --git a/SOURCES/0001-desktop-icons-Use-a-single-unique-name-to-access-nau.patch b/SOURCES/0001-desktop-icons-Use-a-single-unique-name-to-access-nau.patch new file mode 100644 index 0000000..a8d7dca --- /dev/null +++ b/SOURCES/0001-desktop-icons-Use-a-single-unique-name-to-access-nau.patch @@ -0,0 +1,28 @@ +From 81b5163b43b7d45ca8bc9205476ef67789e283a4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 29 Nov 2021 16:48:53 +0100 +Subject: [PATCH] desktop-icons: Use a single unique name to access nautilus + +... otherwise dbus-daemon will assume that activating one of the +services failed, because its executable exits early (after activating +the primary instance). +--- + extensions/desktop-icons/dbusUtils.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/desktop-icons/dbusUtils.js b/extensions/desktop-icons/dbusUtils.js +index 19fe9878..b44ffa59 100644 +--- a/extensions/desktop-icons/dbusUtils.js ++++ b/extensions/desktop-icons/dbusUtils.js +@@ -64,7 +64,7 @@ function init() { + + FreeDesktopFileManagerProxy = new FreeDesktopFileManagerProxyInterface( + Gio.DBus.session, +- 'org.freedesktop.FileManager1', ++ 'org.gnome.Nautilus', + '/org/freedesktop/FileManager1', + (proxy, error) => { + if (error) { +-- +2.33.1 + diff --git a/SOURCES/0001-fileItem-Ignore-double-click-distance-clicking-on-it.patch b/SOURCES/0001-fileItem-Ignore-double-click-distance-clicking-on-it.patch new file mode 100644 index 0000000..592f01c --- /dev/null +++ b/SOURCES/0001-fileItem-Ignore-double-click-distance-clicking-on-it.patch @@ -0,0 +1,83 @@ +From f78b19068654412ca9e73a229e1537d080759c47 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Wed, 27 Jan 2021 16:55:10 +0100 +Subject: [PATCH] fileItem: Ignore double click distance clicking on items + +Imitate the behavior of Nautilus canvas WRT double clicks being +handled on all of the icon(s) without accounting for the double +click distance. As the extension does already lean on Nautilus +look & feel, it seems to make sense doing this. + +This is not as crucial for mice as it is for touchscreens, where +the default 5px limit may be a bit on the short side depending +on device sensitivity. +--- + extensions/desktop-icons/fileItem.js | 26 +++++++++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index d6d43c9..5d3195f 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -65,6 +65,9 @@ var FileItem = class { + this._setMetadataCancellable = null; + this._queryFileInfoCancellable = null; + this._isSpecial = this._fileExtra != Prefs.FileType.NONE; ++ this._lastClickTime = 0; ++ this._lastClickButton = 0; ++ this._clickCount = 0; + + this._file = file; + +@@ -642,7 +645,24 @@ var FileItem = class { + DesktopIconsUtil.launchTerminal(this.file.get_path()); + } + ++ _updateClickState(event) { ++ let settings = Clutter.Settings.get_default(); ++ if ((event.get_button() == this._lastClickButton) && ++ ((event.get_time() - this._lastClickTime) < settings.double_click_time)) ++ this._clickCount++; ++ else ++ this._clickCount = 1; ++ ++ this._lastClickTime = event.get_time(); ++ this._lastClickButton = event.get_button(); ++ } ++ ++ _getClickCount() { ++ return this._clickCount; ++ } ++ + _onPressButton(actor, event) { ++ this._updateClickState(event); + let button = event.get_button(); + if (button == 3) { + if (!this.isSelected) +@@ -661,7 +681,7 @@ var FileItem = class { + this._actionTrash.setSensitive(!specialFilesSelected); + return Clutter.EVENT_STOP; + } else if (button == 1) { +- if (event.get_click_count() == 1) { ++ if (this._getClickCount() == 1) { + let [x, y] = event.get_coords(); + this._primaryButtonPressed = true; + this._buttonPressInitialX = x; +@@ -710,12 +730,12 @@ var FileItem = class { + this._primaryButtonPressed = false; + let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK); + let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK); +- if ((event.get_click_count() == 1) && Prefs.CLICK_POLICY_SINGLE && !shiftPressed && !controlPressed) ++ if ((this._getClickCount() == 1) && Prefs.CLICK_POLICY_SINGLE && !shiftPressed && !controlPressed) + this.doOpen(); + this.emit('selected', shiftPressed || controlPressed, false, true); + return Clutter.EVENT_STOP; + } +- if ((event.get_click_count() == 2) && (!Prefs.CLICK_POLICY_SINGLE)) ++ if ((this._getClickCount() == 2) && (!Prefs.CLICK_POLICY_SINGLE)) + this.doOpen(); + } + return Clutter.EVENT_PROPAGATE; +-- +2.29.2 + diff --git a/SOURCES/0001-fileItem-Just-destroy-menus.patch b/SOURCES/0001-fileItem-Just-destroy-menus.patch new file mode 100644 index 0000000..012428b --- /dev/null +++ b/SOURCES/0001-fileItem-Just-destroy-menus.patch @@ -0,0 +1,31 @@ +From 506c6d69eaa5e056d9580a28e9c200586b0e1fb0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 2 Dec 2022 15:20:40 +0100 +Subject: [PATCH] fileItem: Just destroy menus + +The menu manager is smart enough to remove the menu automatically, +and the actor will be destroyed alongside the menu. Not doing those +actions explicitly allows the automatic handling to proceed without +confusing the grab state. +--- + extensions/desktop-icons/fileItem.js | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index 44a93352..f2f03440 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -575,10 +575,6 @@ var FileItem = class { + + _removeMenu() { + if (this._menu != null) { +- if (this._menuManager != null) +- this._menuManager.removeMenu(this._menu); +- +- Main.layoutManager.uiGroup.remove_child(this._menu.actor); + this._menu.destroy(); + this._menu = null; + } +-- +2.38.1 + diff --git a/SOURCES/0001-fileItem-Support-.desktop-files-of-type-Link.patch b/SOURCES/0001-fileItem-Support-.desktop-files-of-type-Link.patch new file mode 100644 index 0000000..f4bf2b4 --- /dev/null +++ b/SOURCES/0001-fileItem-Support-.desktop-files-of-type-Link.patch @@ -0,0 +1,147 @@ +From be4ab59a3f2bb9829dde390db3dd8868a08840eb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 2 Dec 2022 19:28:54 +0100 +Subject: [PATCH] fileItem: Support .desktop files of type Link + +Gio only has direct support for .desktop files of type Application. + +However in the context of desktop icons (and file managers), shortcuts +of URLs are useful as well, so add explicit support for .desktop files +of type Link. +--- + extensions/desktop-icons/fileItem.js | 71 +++++++++++++++++++++++----- + 1 file changed, 60 insertions(+), 11 deletions(-) + +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index f2f03440..1c9a1e55 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -239,12 +239,32 @@ var FileItem = class { + log(`desktop-icons: File ${this._displayName} is writable by others - will not allow launching`); + + if (this._isDesktopFile) { +- this._desktopFile = Gio.DesktopAppInfo.new_from_filename(this._file.get_path()); +- if (!this._desktopFile) { +- log(`Couldn’t parse ${this._displayName} as a desktop file, will treat it as a regular file.`); ++ try { ++ const keyFile = new GLib.KeyFile(); ++ keyFile.load_from_file(this._file.get_path(), GLib.KeyFileFlags.NONE); ++ ++ const type = keyFile.get_string( ++ GLib.KEY_FILE_DESKTOP_GROUP, GLib.KEY_FILE_DESKTOP_KEY_TYPE); ++ switch (type) { ++ case GLib.KEY_FILE_DESKTOP_TYPE_APPLICATION: ++ this._desktopFile = Gio.DesktopAppInfo.new_from_keyfile(keyFile); ++ if (!this._desktopFile) { ++ log(`Couldn’t parse ${this._displayName} as a desktop file, will treat it as a regular file.`); ++ this._isValidDesktopFile = false; ++ } else { ++ this._isValidDesktopFile = true; ++ } ++ break; ++ case GLib.KEY_FILE_DESKTOP_TYPE_LINK: ++ const url = keyFile.get_string( ++ GLib.KEY_FILE_DESKTOP_GROUP, GLib.KEY_FILE_DESKTOP_KEY_URL); ++ if (url) ++ this._linkFile = keyFile; ++ default: // fall-through ++ this._isValidDesktopFile = false; ++ } ++ } catch (e) { + this._isValidDesktopFile = false; +- } else { +- this._isValidDesktopFile = true; + } + } else { + this._isValidDesktopFile = false; +@@ -356,8 +376,17 @@ var FileItem = class { + if (this._isBrokenSymlink) { + this._icon.child = this._createEmblemedStIcon(null, 'text-x-generic'); + } else { +- if (this.trustedDesktopFile && this._desktopFile.has_key('Icon')) +- this._icon.child = this._createEmblemedStIcon(null, this._desktopFile.get_string('Icon')); ++ let iconName = null; ++ ++ try { ++ if (this.trustedDesktopFile) ++ iconName = this._desktopFile.get_string('Icon'); ++ else if (this._linkFile) ++ iconName = this._linkFile.get_string(GLib.KEY_FILE_DESKTOP_GROUP, GLib.KEY_FILE_DESKTOP_KEY_ICON); ++ } catch (e) {} ++ ++ if (iconName) ++ this._icon.child = this._createEmblemedStIcon(null, iconName); + else + this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null); + } +@@ -411,7 +440,7 @@ var FileItem = class { + itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-unreadable'))); + else + itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-symbolic-link'))); +- } else if (this.trustedDesktopFile) { ++ } else if (this.trustedDesktopFile || this._linkFile) { + itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-symbolic-link'))); + } + +@@ -440,6 +469,12 @@ var FileItem = class { + return; + } + ++ if (this._linkFile) { ++ this._openUri(this._linkFile.get_string( ++ GLib.KEY_FILE_DESKTOP_GROUP, GLib.KEY_FILE_DESKTOP_KEY_URL)); ++ return; ++ } ++ + if (this._attributeCanExecute && + !this._isDirectory && + !this._isValidDesktopFile && +@@ -449,13 +484,17 @@ var FileItem = class { + return; + } + +- Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(), ++ this._openUri(this.file.get_uri()); ++ } ++ ++ _openUri(uri) { ++ Gio.AppInfo.launch_default_for_uri_async(uri, + null, null, + (source, result) => { + try { + Gio.AppInfo.launch_default_for_uri_finish(result); + } catch (e) { +- log('Error opening file ' + this.file.get_uri() + ': ' + e.message); ++ log('Error opening file ' + uri + ': ' + e.message); + } + } + ); +@@ -555,7 +594,9 @@ var FileItem = class { + } + + canRename() { +- return !this.trustedDesktopFile && this._fileExtra == Prefs.FileType.NONE; ++ return !this.trustedDesktopFile && ++ !this._linkFile && ++ this._fileExtra == Prefs.FileType.NONE; + } + + _doOpenWith() { +@@ -819,6 +860,14 @@ var FileItem = class { + if (this.trustedDesktopFile) + return this._desktopFile.get_name(); + ++ if (this._linkFile) { ++ try { ++ const name = this._linkFile.get_string( ++ GLib.KEY_FILE_DESKTOP_GROUP, GLib.KEY_FILE_DESKTOP_KEY_NAME); ++ return name; ++ } catch (e) {} ++ } ++ + return this._displayName || null; + } + +-- +2.38.1 + diff --git a/SOURCES/0001-general-launch-only-executable-files.patch b/SOURCES/0001-general-launch-only-executable-files.patch new file mode 100644 index 0000000..5e90b46 --- /dev/null +++ b/SOURCES/0001-general-launch-only-executable-files.patch @@ -0,0 +1,45 @@ +From ee89a91a9ac235b69ff3c47af14d702c0309e892 Mon Sep 17 00:00:00 2001 +From: Sergio Costas +Date: Thu, 25 Jul 2019 00:12:09 +0200 +Subject: [PATCH] general: launch only executable files + +Until now, if a file has the "execute" flag, clicking on it will try +to execute it, no matter if it is really an executable. This means +that a non-executable file (like a JPEG picture, or a text file) +won't be opened with its desired application if it has set the +executable flag. + +This patch fixes this, by ensuring that the only files that can be +executed when the "execute" flag is set, are the ones that makes +sense to execute. + +Fixes https://gitlab.gnome.org/World/ShellExtensions/desktop-icons/issues/144 +--- + extensions/desktop-icons/fileItem.js | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index d6d43c9f..44a93352 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -440,10 +440,13 @@ var FileItem = class { + return; + } + +- if (this._attributeCanExecute && !this._isDirectory && !this._isValidDesktopFile) { +- if (this._execLine) +- Util.spawnCommandLine(this._execLine); +- return; ++ if (this._attributeCanExecute && ++ !this._isDirectory && ++ !this._isValidDesktopFile && ++ Gio.content_type_can_be_executable(this._attributeContentType)) { ++ if (this._execLine) ++ Util.spawnCommandLine(this._execLine); ++ return; + } + + Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(), +-- +2.31.1 + diff --git a/SOURCES/0001-gesture-inhibitor-Allow-inhibiting-workspace-switch-.patch b/SOURCES/0001-gesture-inhibitor-Allow-inhibiting-workspace-switch-.patch new file mode 100644 index 0000000..8100011 --- /dev/null +++ b/SOURCES/0001-gesture-inhibitor-Allow-inhibiting-workspace-switch-.patch @@ -0,0 +1,51 @@ +From ce75829479b1e7bf99e74bf835174e91c8da2276 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 9 Dec 2022 15:31:08 +0100 +Subject: [PATCH] gesture-inhibitor: Allow inhibiting workspace switch gesture + +--- + extensions/gesture-inhibitor/extension.js | 5 ++++- + .../org.gnome.shell.extensions.gesture-inhibitor.gschema.xml | 4 ++++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/extensions/gesture-inhibitor/extension.js b/extensions/gesture-inhibitor/extension.js +index e74ede2f..bf02d075 100644 +--- a/extensions/gesture-inhibitor/extension.js ++++ b/extensions/gesture-inhibitor/extension.js +@@ -37,6 +37,8 @@ class Extension { + this._showOverview = a; + else if (a instanceof WindowManager.AppSwitchAction) + this._appSwitch = a; ++ else if (a instanceof WindowManager.WorkspaceSwitchAction) ++ this._workspaceSwitch = a; + else if (a instanceof EdgeDragAction.EdgeDragAction && + a._side == St.Side.BOTTOM) + this._showOsk = a; +@@ -52,7 +54,8 @@ class Extension { + { setting: 'app-switch', action: this._appSwitch }, + { setting: 'show-osk', action: this._showOsk }, + { setting: 'unfullscreen', action: this._unfullscreen }, +- { setting: 'show-app-grid', action: this._showAppGrid } ++ { setting: 'show-app-grid', action: this._showAppGrid }, ++ { setting: 'workspace-switch', action: this._workspaceSwitch }, + ]; + } + +diff --git a/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml b/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml +index 1d67dcc0..a5e97a3d 100644 +--- a/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml ++++ b/extensions/gesture-inhibitor/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml +@@ -16,6 +16,10 @@ + true + Application switch gesture + ++ ++ true ++ Workspace switch gesture ++ + + true + Unfullscreen gesture +-- +2.38.1 + diff --git a/SOURCES/0001-gesture-inhibitor-Put-a-foot-down-with-self-enabling.patch b/SOURCES/0001-gesture-inhibitor-Put-a-foot-down-with-self-enabling.patch new file mode 100644 index 0000000..af7d0e7 --- /dev/null +++ b/SOURCES/0001-gesture-inhibitor-Put-a-foot-down-with-self-enabling.patch @@ -0,0 +1,41 @@ +From dfdd10b46d670674d5e0e38f7adcd007f5884822 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Wed, 29 Sep 2021 14:33:25 +0200 +Subject: [PATCH] gesture-inhibitor: Put a foot down with self-enabling + gestures + +If a gesture (unfullscreen, I'm looking at you) controls its 'enabled' +property, it will bypass the will of this extension. Make it sure that +gestures are forced-off if the extension says so. +--- + extensions/gesture-inhibitor/extension.js | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/extensions/gesture-inhibitor/extension.js b/extensions/gesture-inhibitor/extension.js +index e74ede2..66c706e 100644 +--- a/extensions/gesture-inhibitor/extension.js ++++ b/extensions/gesture-inhibitor/extension.js +@@ -59,13 +59,19 @@ class Extension { + enable() { + this._map.forEach(m => { + this._settings.bind(m.setting, m.action, 'enabled', +- Gio.SettingsBindFlags.DEFAULT); ++ Gio.SettingsBindFlags.GET); ++ m.handler = m.action.connect('notify::enabled', () => { ++ if (m.action.enabled && !this._settings.get_boolean(m.setting)) ++ m.action.enabled = this._settings.get_boolean(m.setting); ++ }); + }); + } + + disable() { + this._map.forEach(m => { + m.action.enabled = true; ++ if (m.handler > 0) ++ m.action.disconnect(m.handler); + }); + } + } +-- +2.31.1 + diff --git a/SOURCES/0001-heads-up-display-Add-extension-for-showing-persisten.patch b/SOURCES/0001-heads-up-display-Add-extension-for-showing-persisten.patch new file mode 100644 index 0000000..4cfdf1d --- /dev/null +++ b/SOURCES/0001-heads-up-display-Add-extension-for-showing-persisten.patch @@ -0,0 +1,831 @@ +From 8da1760af68496c6073be4d6b3c8266b64347925 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 24 Aug 2021 15:03:57 -0400 +Subject: [PATCH] heads-up-display: Add extension for showing persistent heads + up display message + +--- + extensions/heads-up-display/extension.js | 320 ++++++++++++++++++ + extensions/heads-up-display/headsUpMessage.js | 150 ++++++++ + extensions/heads-up-display/meson.build | 8 + + extensions/heads-up-display/metadata.json.in | 11 + + ...ll.extensions.heads-up-display.gschema.xml | 54 +++ + extensions/heads-up-display/prefs.js | 175 ++++++++++ + extensions/heads-up-display/stylesheet.css | 32 ++ + meson.build | 1 + + 8 files changed, 751 insertions(+) + create mode 100644 extensions/heads-up-display/extension.js + create mode 100644 extensions/heads-up-display/headsUpMessage.js + create mode 100644 extensions/heads-up-display/meson.build + create mode 100644 extensions/heads-up-display/metadata.json.in + create mode 100644 extensions/heads-up-display/org.gnome.shell.extensions.heads-up-display.gschema.xml + create mode 100644 extensions/heads-up-display/prefs.js + create mode 100644 extensions/heads-up-display/stylesheet.css + +diff --git a/extensions/heads-up-display/extension.js b/extensions/heads-up-display/extension.js +new file mode 100644 +index 00000000..e4ef9e85 +--- /dev/null ++++ b/extensions/heads-up-display/extension.js +@@ -0,0 +1,320 @@ ++/* exported init enable disable */ ++ ++ ++const Signals = imports.signals; ++ ++const { ++ Atk, Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St, ++} = imports.gi; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++ ++const Main = imports.ui.main; ++const HeadsUpMessage = Me.imports.headsUpMessage; ++ ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++ ++class Extension { ++ constructor() { ++ ExtensionUtils.initTranslations(); ++ } ++ ++ enable() { ++ this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.heads-up-display'); ++ this._idleTimeoutChangedId = this._settings.connect('changed::idle-timeout', this._onIdleTimeoutChanged.bind(this)); ++ this._settingsChangedId = this._settings.connect('changed', this._updateMessage.bind(this)); ++ ++ this._idleMonitor = Meta.IdleMonitor.get_core(); ++ this._messageInhibitedUntilIdle = false; ++ this._oldMapWindow = Main.wm._mapWindow; ++ Main.wm._mapWindow = this._mapWindow; ++ this._windowManagerMapId = global.window_manager.connect('map', this._onWindowMap.bind(this)); ++ ++ if (Main.layoutManager._startingUp) ++ this._startupCompleteId = Main.layoutManager.connect('startup-complete', this._onStartupComplete.bind(this)); ++ else ++ this._onStartupComplete(this); ++ } ++ ++ disable() { ++ this._dismissMessage(); ++ ++ if (this._idleWatchId) { ++ this._idleMonitor.remove_watch(this._idleWatchId); ++ this._idleWatchId = 0; ++ } ++ ++ if (this._sessionModeUpdatedId) { ++ Main.sessionMode.disconnect(this._sessionModeUpdatedId); ++ this._sessionModeUpdatedId = 0; ++ } ++ ++ if (this._overviewShowingId) { ++ Main.overview.disconnect(this._overviewShowingId); ++ this._overviewShowingId = 0; ++ } ++ ++ if (this._overviewHiddenId) { ++ Main.overview.disconnect(this._overviewHiddenId); ++ this._overviewHiddenId = 0; ++ } ++ ++ if (this._panelConnectionId) { ++ Main.layoutManager.panelBox.disconnect(this._panelConnectionId); ++ this._panelConnectionId = 0; ++ } ++ ++ if (this._oldMapWindow) { ++ Main.wm._mapWindow = this._oldMapWindow; ++ this._oldMapWindow = null; ++ } ++ ++ if (this._windowManagerMapId) { ++ global.window_manager.disconnect(this._windowManagerMapId); ++ this._windowManagerMapId = 0; ++ } ++ ++ if (this._startupCompleteId) { ++ Main.layoutManager.disconnect(this._startupCompleteId); ++ this._startupCompleteId = 0; ++ } ++ ++ if (this._settingsChangedId) { ++ this._settings.disconnect(this._settingsChangedId); ++ this._settingsChangedId = 0; ++ } ++ } ++ ++ _onWindowMap(shellwm, actor) { ++ let windowObject = actor.meta_window; ++ let windowType = windowObject.get_window_type(); ++ ++ if (windowType != Meta.WindowType.NORMAL) ++ return; ++ ++ if (!this._message || !this._message.visible) ++ return; ++ ++ let messageRect = new Meta.Rectangle({ x: this._message.x, y: this._message.y, width: this._message.width, height: this._message.height }); ++ let windowRect = windowObject.get_frame_rect(); ++ ++ if (windowRect.intersect(messageRect)) { ++ windowObject.move_frame(false, windowRect.x, this._message.y + this._message.height); ++ } ++ } ++ ++ _onStartupComplete() { ++ this._overviewShowingId = Main.overview.connect('showing', this._updateMessage.bind(this)); ++ this._overviewHiddenId = Main.overview.connect('hidden', this._updateMessage.bind(this)); ++ this._panelConnectionId = Main.layoutManager.panelBox.connect('notify::visible', this._updateMessage.bind(this)); ++ this._sessionModeUpdatedId = Main.sessionMode.connect('updated', this._onSessionModeUpdated.bind(this)); ++ ++ this._updateMessage(); ++ } ++ ++ _onSessionModeUpdated() { ++ if (!Main.sessionMode.hasWindows) ++ this._messageInhibitedUntilIdle = false; ++ this._updateMessage(); ++ } ++ ++ _onIdleTimeoutChanged() { ++ if (this._idleWatchId) { ++ this._idleMonitor.remove_watch(this._idleWatchId); ++ this._idleWatchId = 0; ++ } ++ this._messageInhibitedUntilIdle = false; ++ } ++ ++ _updateMessage() { ++ if (this._messageInhibitedUntilIdle) { ++ if (this._message) ++ this._dismissMessage(); ++ return; ++ } ++ ++ if (this._idleWatchId) { ++ this._idleMonitor.remove_watch(this._idleWatchId); ++ this._idleWatchId = 0; ++ } ++ ++ if (Main.sessionMode.hasOverview && Main.overview.visible) { ++ this._dismissMessage(); ++ return; ++ } ++ ++ if (!Main.layoutManager.panelBox.visible) { ++ this._dismissMessage(); ++ return; ++ } ++ ++ let supportedModes = []; ++ ++ if (this._settings.get_boolean('show-when-unlocked')) ++ supportedModes.push('user'); ++ ++ if (this._settings.get_boolean('show-when-unlocking')) ++ supportedModes.push('unlock-dialog'); ++ ++ if (this._settings.get_boolean('show-when-locked')) ++ supportedModes.push('lock-screen'); ++ ++ if (this._settings.get_boolean('show-on-login-screen')) ++ supportedModes.push('gdm'); ++ ++ if (!supportedModes.includes(Main.sessionMode.currentMode) && ++ !supportedModes.includes(Main.sessionMode.parentMode)) { ++ this._dismissMessage(); ++ return; ++ } ++ ++ let heading = this._settings.get_string('message-heading'); ++ let body = this._settings.get_string('message-body'); ++ ++ if (!heading && !body) { ++ this._dismissMessage(); ++ return; ++ } ++ ++ if (!this._message) { ++ this._message = new HeadsUpMessage.HeadsUpMessage(heading, body); ++ ++ this._message.connect('notify::allocation', this._adaptSessionForMessage.bind(this)); ++ this._message.connect('clicked', this._onMessageClicked.bind(this)); ++ } ++ ++ this._message.reactive = true; ++ this._message.track_hover = true; ++ ++ this._message.setHeading(heading); ++ this._message.setBody(body); ++ ++ if (!Main.sessionMode.hasWindows) { ++ this._message.track_hover = false; ++ this._message.reactive = false; ++ } ++ } ++ ++ _onMessageClicked() { ++ if (!Main.sessionMode.hasWindows) ++ return; ++ ++ if (this._idleWatchId) { ++ this._idleMonitor.remove_watch(this._idleWatchId); ++ this._idleWatchId = 0; ++ } ++ ++ let idleTimeout = this._settings.get_uint('idle-timeout'); ++ this._idleWatchId = this._idleMonitor.add_idle_watch(idleTimeout * 1000, this._onUserIdle.bind(this)); ++ this._messageInhibitedUntilIdle = true; ++ this._updateMessage(); ++ } ++ ++ _onUserIdle() { ++ this._messageInhibitedUntilIdle = false; ++ this._updateMessage(); ++ } ++ ++ _dismissMessage() { ++ if (!this._message) { ++ return; ++ } ++ ++ this._message.visible = false; ++ this._message.destroy(); ++ this._message = null; ++ this._resetMessageTray(); ++ this._resetLoginDialog(); ++ } ++ ++ _resetMessageTray() { ++ if (!Main.messageTray) ++ return; ++ ++ Main.messageTray.actor.set_translation(0, 0, 0); ++ } ++ ++ _alignMessageTray() { ++ if (!Main.messageTray) ++ return; ++ ++ if (!this._message || !this._message.visible) { ++ this._resetMessageTray() ++ return; ++ } ++ ++ let panelBottom = Main.layoutManager.panelBox.y + Main.layoutManager.panelBox.height; ++ let messageBottom = this._message.y + this._message.height; ++ ++ Main.messageTray.actor.set_translation(0, messageBottom - panelBottom, 0); ++ } ++ ++ _resetLoginDialog() { ++ if (!Main.sessionMode.isGreeter) ++ return; ++ ++ if (!Main.screenShield || !Main.screenShield._dialog) ++ return; ++ ++ let dialog = Main.screenShield._dialog; ++ ++ if (this._authPromptAllocatedId) { ++ dialog.disconnect(this._authPromptAllocatedId); ++ this._authPromptAllocatedId = 0; ++ } ++ ++ dialog.style = null; ++ dialog._bannerView.style = null; ++ } ++ ++ _adaptLoginDialogForMessage() { ++ if (!Main.sessionMode.isGreeter) ++ return; ++ ++ if (!Main.screenShield || !Main.screenShield._dialog) ++ return; ++ ++ if (!this._message || !this._message.visible) { ++ this._resetLoginDialog() ++ return; ++ } ++ ++ let dialog = Main.screenShield._dialog; ++ ++ let messageHeight = this._message.y + this._message.height; ++ if (dialog._logoBin.visible) ++ messageHeight -= dialog._logoBin.height; ++ ++ if (messageHeight <= 0) { ++ dialog.style = null; ++ dialog._bannerView.style = null; ++ } else { ++ dialog.style = `margin-top: ${messageHeight}px;`; ++ ++ let bannerOnSide = dialog._bannerView.x + dialog._bannerView.width < dialog._authPrompt.actor.x; ++ ++ if (bannerOnSide) ++ dialog._bannerView.style = `margin-bottom: ${messageHeight}px;`; ++ else ++ dialog._bannerView.style = `margin-top: ${messageHeight}px`; ++ } ++ } ++ ++ _adaptSessionForMessage() { ++ this._alignMessageTray(); ++ ++ if (Main.sessionMode.isGreeter) { ++ this._adaptLoginDialogForMessage(); ++ if (!this._authPromptAllocatedId) { ++ let dialog = Main.screenShield._dialog; ++ this._authPromptAllocatedId = dialog._authPrompt.actor.connect("notify::allocation", this._adaptLoginDialogForMessage.bind(this)); ++ } ++ } ++ } ++} ++ ++function init() { ++ return new Extension(); ++} +diff --git a/extensions/heads-up-display/headsUpMessage.js b/extensions/heads-up-display/headsUpMessage.js +new file mode 100644 +index 00000000..d828d8c9 +--- /dev/null ++++ b/extensions/heads-up-display/headsUpMessage.js +@@ -0,0 +1,150 @@ ++const { Atk, Clutter, GObject, Pango, St } = imports.gi; ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++const Signals = imports.signals; ++ ++var HeadsUpMessageBodyLabel = GObject.registerClass({ ++}, class HeadsUpMessageBodyLabel extends St.Label { ++ _init(params) { ++ super._init(params); ++ ++ this.clutter_text.single_line_mode = false; ++ this.clutter_text.line_wrap = true; ++ } ++ ++ vfunc_get_preferred_width(forHeight) { ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); ++ ++ let [labelMinimumWidth, labelNaturalWidth] = super.vfunc_get_preferred_width(forHeight); ++ ++ labelMinimumWidth = Math.min(labelMinimumWidth, .75 * workArea.width); ++ labelNaturalWidth = Math.min(labelNaturalWidth, .75 * workArea.width); ++ ++ return [labelMinimumWidth, labelNaturalWidth]; ++ } ++ ++ vfunc_get_preferred_height(forWidth) { ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); ++ let labelHeightUpperBound = .25 * workArea.height; ++ ++ this.clutter_text.single_line_mode = true; ++ this.clutter_text.line_wrap = false; ++ let [lineHeight] = super.vfunc_get_preferred_height(-1); ++ let numberOfLines = Math.floor(labelHeightUpperBound / lineHeight); ++ numberOfLines = Math.max(numberOfLines, 1); ++ ++ let labelHeight = lineHeight * numberOfLines; ++ ++ this.clutter_text.single_line_mode = false; ++ this.clutter_text.line_wrap = true; ++ let [labelMinimumHeight, labelNaturalHeight] = super.vfunc_get_preferred_height(forWidth); ++ ++ labelMinimumHeight = Math.min(labelMinimumHeight, labelHeight); ++ labelNaturalHeight = Math.min(labelNaturalHeight, labelHeight); ++ ++ return [labelMinimumHeight, labelNaturalHeight]; ++ } ++ ++ vfunc_allocate(box, flags) { ++ if (!this.visible) ++ return; ++ ++ super.vfunc_allocate(box, flags); ++ } ++}); ++ ++var HeadsUpMessage = GObject.registerClass({ ++}, class HeadsUpMessage extends St.Button { ++ _init(heading, body) { ++ super._init({ ++ style_class: 'message', ++ accessible_role: Atk.Role.NOTIFICATION, ++ can_focus: false, ++ }); ++ ++ Main.layoutManager.addChrome(this, { affectsInputRegion: true }); ++ ++ this.add_style_class_name('heads-up-display-message'); ++ ++ this._panelAllocationId = Main.layoutManager.panelBox.connect ("notify::allocation", this._alignWithPanel.bind(this)); ++ this.connect("notify::allocation", this._alignWithPanel.bind(this)); ++ ++ this._messageTraySnappingId = Main.messageTray.connect ("notify::y", () => { ++ if (!this.visible) ++ return; ++ ++ if (!Main.messageTray.visible) ++ return; ++ ++ if (Main.messageTray.y >= this.y && Main.messageTray.y < this.y + this.height) ++ Main.messageTray.y = this.y + this.height; ++ }); ++ ++ ++ let contentsBox = new St.BoxLayout({ style_class: 'heads-up-message-content', ++ vertical: true, ++ x_align: Clutter.ActorAlign.CENTER }); ++ this.add_actor(contentsBox); ++ ++ this.headingLabel = new St.Label({ style_class: 'heads-up-message-heading', ++ x_expand: true, ++ x_align: Clutter.ActorAlign.CENTER }); ++ this.setHeading(heading); ++ contentsBox.add_actor(this.headingLabel); ++ this.contentsBox = contentsBox; ++ ++ this.bodyLabel = new HeadsUpMessageBodyLabel({ style_class: 'heads-up-message-body', ++ x_expand: true, ++ y_expand: true }); ++ contentsBox.add_actor(this.bodyLabel); ++ ++ this.setBody(body); ++ this.bodyLabel.clutter_text.label = this.bodyLabel; ++ } ++ ++ _alignWithPanel() { ++ if (!this.visible) ++ return; ++ ++ this.x = Main.panel.actor.x; ++ this.x += Main.panel.actor.width / 2; ++ this.x -= this.width / 2; ++ this.x = Math.floor(this.x); ++ this.y = Main.panel.actor.y + Main.panel.actor.height; ++ this.queue_relayout(); ++ } ++ ++ setHeading(text) { ++ if (text) { ++ let heading = text ? text.replace(/\n/g, ' ') : ''; ++ this.headingLabel.text = heading; ++ this.headingLabel.visible = true; ++ } else { ++ this.headingLabel.text = text; ++ this.headingLabel.visible = false; ++ } ++ } ++ ++ setBody(text) { ++ this.bodyLabel.text = text; ++ if (text) { ++ this.bodyLabel.visible = true; ++ } else { ++ this.bodyLabel.visible = false; ++ } ++ } ++ ++ destroy() { ++ if (this._panelAllocationId) { ++ Main.layoutManager.panelBox.disconnect(this._panelAllocationId); ++ this._panelAllocationId = 0; ++ } ++ ++ if (this._messageTraySnappingId) { ++ Main.messageTray.disconnect(this._messageTraySnappingId); ++ this._messageTraySnappingId = 0; ++ } ++ ++ super.destroy(); ++ } ++}); +diff --git a/extensions/heads-up-display/meson.build b/extensions/heads-up-display/meson.build +new file mode 100644 +index 00000000..40c3de0a +--- /dev/null ++++ b/extensions/heads-up-display/meson.build +@@ -0,0 +1,8 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_sources += files('headsUpMessage.js', 'prefs.js') ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') +diff --git a/extensions/heads-up-display/metadata.json.in b/extensions/heads-up-display/metadata.json.in +new file mode 100644 +index 00000000..e7ab71aa +--- /dev/null ++++ b/extensions/heads-up-display/metadata.json.in +@@ -0,0 +1,11 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"gettext-domain": "@gettext_domain@", ++"name": "Heads-up Display Message", ++"description": "Add a message to be displayed on screen always above all windows and chrome.", ++"original-authors": [ "rstrode@redhat.com" ], ++"shell-version": [ "@shell_current@" ], ++"url": "@url@", ++"session-modes": [ "gdm", "lock-screen", "unlock-dialog", "user" ] ++} +diff --git a/extensions/heads-up-display/org.gnome.shell.extensions.heads-up-display.gschema.xml b/extensions/heads-up-display/org.gnome.shell.extensions.heads-up-display.gschema.xml +new file mode 100644 +index 00000000..ea1f3774 +--- /dev/null ++++ b/extensions/heads-up-display/org.gnome.shell.extensions.heads-up-display.gschema.xml +@@ -0,0 +1,54 @@ ++ ++ ++ ++ 30 ++ Idle Timeout ++ ++ Number of seconds until message is reshown after user goes idle. ++ ++ ++ ++ "" ++ Message to show at top of display ++ ++ The top line of the heads up display message. ++ ++ ++ ++ "" ++ Banner message ++ ++ A message to always show at the top of the screen. ++ ++ ++ ++ true ++ Show on login screen ++ ++ Whether or not the message should display on the login screen ++ ++ ++ ++ false ++ Show on screen shield ++ ++ Whether or not the message should display when the screen is locked ++ ++ ++ ++ false ++ Show on unlock screen ++ ++ Whether or not the message should display on the unlock screen. ++ ++ ++ ++ false ++ Show in user session ++ ++ Whether or not the message should display when the screen is unlocked. ++ ++ ++ ++ +diff --git a/extensions/heads-up-display/prefs.js b/extensions/heads-up-display/prefs.js +new file mode 100644 +index 00000000..b4b6f94c +--- /dev/null ++++ b/extensions/heads-up-display/prefs.js +@@ -0,0 +1,175 @@ ++ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const { Gio, GObject, Gdk, Gtk } = imports.gi; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++const N_ = e => e; ++const cssData = ` ++ .no-border { ++ border: none; ++ } ++ ++ .border { ++ border: 1px solid; ++ border-radius: 3px; ++ border-color: #b6b6b3; ++ box-shadow: inset 0 0 0 1px rgba(74, 144, 217, 0); ++ background-color: white; ++ } ++ ++ .margins { ++ padding-left: 8px; ++ padding-right: 8px; ++ padding-bottom: 8px; ++ } ++ ++ .message-label { ++ font-weight: bold; ++ } ++`; ++ ++var settings; ++ ++function init() { ++ settings = ExtensionUtils.getSettings("org.gnome.shell.extensions.heads-up-display"); ++ let cssProvider = new Gtk.CssProvider(); ++ cssProvider.load_from_data(cssData); ++ ++ let screen = Gdk.Screen.get_default(); ++ Gtk.StyleContext.add_provider_for_screen(screen, cssProvider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); ++} ++ ++function buildPrefsWidget() { ++ ExtensionUtils.initTranslations(); ++ ++ let contents = new Gtk.Box({ ++ orientation: Gtk.Orientation.VERTICAL, ++ border_width: 20, ++ spacing: 10, ++ }); ++ ++ contents.add(buildSwitch('show-when-locked', _("Show message when screen is locked"))); ++ contents.add(buildSwitch('show-when-unlocking', _("Show message on unlock screen"))); ++ contents.add(buildSwitch('show-when-unlocked', _("Show message when screen is unlocked"))); ++ contents.add(buildSpinButton('idle-timeout', _("Seconds after user goes idle before reshowing message"))); ++ ++ let outerMessageBox = new Gtk.Box({ ++ orientation: Gtk.Orientation.VERTICAL, ++ border_width: 0, ++ spacing: 5, ++ }); ++ contents.add(outerMessageBox); ++ ++ let messageLabel = new Gtk.Label({ ++ label: 'Message', ++ halign: Gtk.Align.START, ++ }); ++ messageLabel.get_style_context().add_class("message-label"); ++ outerMessageBox.add(messageLabel); ++ ++ let innerMessageBox = new Gtk.Box({ ++ orientation: Gtk.Orientation.VERTICAL, ++ border_width: 0, ++ spacing: 0, ++ }); ++ innerMessageBox.get_style_context().add_class("border"); ++ outerMessageBox.add(innerMessageBox); ++ ++ innerMessageBox.add(buildEntry('message-heading', _("Message Heading"))); ++ innerMessageBox.add(buildTextView('message-body', _("Message Body"))); ++ contents.show_all(); ++ return contents; ++} ++ ++function buildTextView(key, labelText) { ++ let textView = new Gtk.TextView({ ++ accepts_tab: false, ++ wrap_mode: Gtk.WrapMode.WORD, ++ }); ++ settings.bind(key, textView.get_buffer(), 'text', Gio.SettingsBindFlags.DEFAULT); ++ ++ let scrolledWindow = new Gtk.ScrolledWindow({ ++ expand: true, ++ }); ++ let styleContext = scrolledWindow.get_style_context(); ++ styleContext.add_class("margins"); ++ ++ scrolledWindow.add(textView); ++ return scrolledWindow; ++} ++function buildEntry(key, labelText) { ++ let entry = new Gtk.Entry({ placeholder_text: labelText }); ++ let styleContext = entry.get_style_context(); ++ styleContext.add_class("no-border"); ++ settings.bind(key, entry, 'text', Gio.SettingsBindFlags.DEFAULT); ++ ++ entry.get_settings()['gtk-entry-select-on-focus'] = false; ++ ++ return entry; ++} ++ ++function buildSpinButton(key, labelText) { ++ let hbox = new Gtk.Box({ ++ orientation: Gtk.Orientation.HORIZONTAL, ++ spacing: 10, ++ }); ++ let label = new Gtk.Label({ ++ label: labelText, ++ xalign: 0, ++ }); ++ let adjustment = new Gtk.Adjustment({ ++ value: 0, ++ lower: 0, ++ upper: 2147483647, ++ step_increment: 1, ++ page_increment: 60, ++ page_size: 60, ++ }); ++ let spinButton = new Gtk.SpinButton({ ++ adjustment: adjustment, ++ climb_rate: 1.0, ++ digits: 0, ++ max_width_chars: 3, ++ width_chars: 3, ++ }); ++ settings.bind(key, spinButton, 'value', Gio.SettingsBindFlags.DEFAULT); ++ hbox.pack_start(label, true, true, 0); ++ hbox.add(spinButton); ++ return hbox; ++} ++ ++function buildSwitch(key, labelText) { ++ let hbox = new Gtk.Box({ ++ orientation: Gtk.Orientation.HORIZONTAL, ++ spacing: 10, ++ }); ++ let label = new Gtk.Label({ ++ label: labelText, ++ xalign: 0, ++ }); ++ let switcher = new Gtk.Switch({ ++ active: settings.get_boolean(key), ++ }); ++ settings.bind(key, switcher, 'active', Gio.SettingsBindFlags.DEFAULT); ++ hbox.pack_start(label, true, true, 0); ++ hbox.add(switcher); ++ return hbox; ++} +diff --git a/extensions/heads-up-display/stylesheet.css b/extensions/heads-up-display/stylesheet.css +new file mode 100644 +index 00000000..93034469 +--- /dev/null ++++ b/extensions/heads-up-display/stylesheet.css +@@ -0,0 +1,32 @@ ++.heads-up-display-message { ++ background-color: rgba(0.24, 0.24, 0.24, 0.80); ++ border: 1px solid black; ++ border-radius: 6px; ++ color: #eeeeec; ++ font-size: 11pt; ++ margin-top: 0.5em; ++ margin-bottom: 0.5em; ++ padding: 0.9em; ++} ++ ++.heads-up-display-message:insensitive { ++ background-color: rgba(0.24, 0.24, 0.24, 0.33); ++} ++ ++.heads-up-display-message:hover { ++ background-color: rgba(0.24, 0.24, 0.24, 0.2); ++ border: 1px solid rgba(0.0, 0.0, 0.0, 0.5); ++ color: #4d4d4d; ++ transition-duration: 250ms; ++} ++ ++.heads-up-message-heading { ++ height: 1.75em; ++ font-size: 1.25em; ++ font-weight: bold; ++ text-align: center; ++} ++ ++.heads-up-message-body { ++ text-align: center; ++} +diff --git a/meson.build b/meson.build +index ba84f8f3..c5fc86ef 100644 +--- a/meson.build ++++ b/meson.build +@@ -44,6 +44,7 @@ classic_extensions = [ + default_extensions = classic_extensions + default_extensions += [ + 'drive-menu', ++ 'heads-up-display', + 'screenshot-window-sizer', + 'windowsNavigator', + 'workspace-indicator' +-- +2.32.0 + diff --git a/SOURCES/0001-top-icons-Don-t-use-wm_class-as-role.patch b/SOURCES/0001-top-icons-Don-t-use-wm_class-as-role.patch new file mode 100644 index 0000000..bc3b89b --- /dev/null +++ b/SOURCES/0001-top-icons-Don-t-use-wm_class-as-role.patch @@ -0,0 +1,27 @@ +From ce48dc2f4fba6a7084540df256cb5b3eb0da43da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 2 Jun 2021 17:32:21 +0200 +Subject: [PATCH] top-icons: Don't use wm_class as role + +This prevents adding icons for multiple instances of the same app, +which may be desirable in some circumstances. +--- + extensions/top-icons/extension.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js +index 79e2f423..3dfba469 100644 +--- a/extensions/top-icons/extension.js ++++ b/extensions/top-icons/extension.js +@@ -63,7 +63,7 @@ class SysTray { + button.destroy(); + }); + +- let role = wmClass || `${icon}`; ++ const role = `${icon}`; + Main.panel.addToStatusArea(role, button); + } + +-- +2.31.1 + diff --git a/SOURCES/0001-window-list-Invalid-current-mode-selected-in-Prefere.patch b/SOURCES/0001-window-list-Invalid-current-mode-selected-in-Prefere.patch new file mode 100644 index 0000000..cf9d160 --- /dev/null +++ b/SOURCES/0001-window-list-Invalid-current-mode-selected-in-Prefere.patch @@ -0,0 +1,55 @@ +From b4eeaf7ea12fa7d9713e80371490d8060396b3cb Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Fri, 17 Apr 2020 09:21:42 +0200 +Subject: [PATCH] window-list: Invalid current mode selected in Preferences + +It seems that gtk+ resets the active radio whenever a new radio button +is added into the group, thus rather restore the current mode after +the group is fully populated. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/119 +--- + extensions/window-list/prefs.js | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/prefs.js b/extensions/window-list/prefs.js +index 78792b5..17e9799 100644 +--- a/extensions/window-list/prefs.js ++++ b/extensions/window-list/prefs.js +@@ -50,6 +50,7 @@ class WindowListPrefsWidget extends Gtk.Grid { + }; + + let radio = null; ++ let currentRadio = null; + for (let i = 0; i < modes.length; i++) { + let mode = modes[i]; + let label = modeLabels[mode]; +@@ -59,18 +60,24 @@ class WindowListPrefsWidget extends Gtk.Grid { + } + + radio = new Gtk.RadioButton({ +- active: currentMode == mode, ++ active: !i, + label: label, + group: radio + }); + grid.add(radio); + ++ if (currentMode === mode) ++ currentRadio = radio; ++ + radio.connect('toggled', button => { + if (button.active) + this._settings.set_string('grouping-mode', mode); + }); + } + ++ if (currentRadio) ++ currentRadio.active = true; ++ + let check = new Gtk.CheckButton({ + label: _('Show on all monitors'), + margin_top: 6 +-- +2.26.2 + diff --git a/SOURCES/0001-window-list-Leave-fake-overview-when-destroyed.patch b/SOURCES/0001-window-list-Leave-fake-overview-when-destroyed.patch new file mode 100644 index 0000000..3c6c7e5 --- /dev/null +++ b/SOURCES/0001-window-list-Leave-fake-overview-when-destroyed.patch @@ -0,0 +1,30 @@ +From ee25c2aac70b86f31c91f6491dad4c67a59bc261 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 26 Jan 2021 21:14:47 +0100 +Subject: [PATCH] window-list: Leave "fake overview" when destroyed + +Otherwise we leave an incomplete overview-like state around, which +can cause issues later when the extension is re-enabled (for example +when coming back from screen lock). + +https://bugzilla.redhat.com/show_bug.cgi?id=1904371 +--- + extensions/window-list/windowPicker.js | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js +index 12a7627..afb5d27 100644 +--- a/extensions/window-list/windowPicker.js ++++ b/extensions/window-list/windowPicker.js +@@ -210,6 +210,8 @@ var WindowPicker = class { + } + + _onDestroy() { ++ this._fakeOverviewVisible(false); ++ + if (this._monitorsChangedId) + Main.layoutManager.disconnect(this._monitorsChangedId); + this._monitorsChangedId = 0; +-- +2.31.1 + diff --git a/SOURCES/add-extra-extensions.patch b/SOURCES/add-extra-extensions.patch new file mode 100644 index 0000000..ea1f191 --- /dev/null +++ b/SOURCES/add-extra-extensions.patch @@ -0,0 +1,72215 @@ +From ed28c7abd7c324dc6071ff96309854b1f5d48761 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 20 May 2015 17:44:50 +0200 +Subject: [PATCH 01/11] Add top-icons extension + +--- + extensions/top-icons/extension.js | 96 +++++++++++++++++++++++++++ + extensions/top-icons/meson.build | 5 ++ + extensions/top-icons/metadata.json.in | 10 +++ + extensions/top-icons/stylesheet.css | 1 + + meson.build | 1 + + 5 files changed, 113 insertions(+) + create mode 100644 extensions/top-icons/extension.js + create mode 100644 extensions/top-icons/meson.build + create mode 100644 extensions/top-icons/metadata.json.in + create mode 100644 extensions/top-icons/stylesheet.css + +diff --git a/extensions/top-icons/extension.js b/extensions/top-icons/extension.js +new file mode 100644 +index 00000000..a8eec13c +--- /dev/null ++++ b/extensions/top-icons/extension.js +@@ -0,0 +1,96 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++/* exported init */ ++ ++const { Clutter, Shell, St } = imports.gi; ++const Main = imports.ui.main; ++const PanelMenu = imports.ui.panelMenu; ++const System = imports.system; ++ ++const PANEL_ICON_SIZE = 16; ++ ++const STANDARD_TRAY_ICON_IMPLEMENTATIONS = [ ++ 'bluetooth-applet', ++ 'gnome-sound-applet', ++ 'nm-applet', ++ 'gnome-power-manager', ++ 'keyboard', ++ 'a11y-keyboard', ++ 'kbd-scrolllock', ++ 'kbd-numlock', ++ 'kbd-capslock', ++ 'ibus-ui-gtk' ++]; ++ ++class SysTray { ++ constructor() { ++ this._icons = []; ++ this._tray = null; ++ } ++ ++ _onTrayIconAdded(o, icon) { ++ let wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : ''; ++ if (STANDARD_TRAY_ICON_IMPLEMENTATIONS.includes(wmClass)) ++ return; ++ ++ let button = new PanelMenu.Button(0.5, null, true); ++ ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ let iconSize = PANEL_ICON_SIZE * scaleFactor; ++ ++ icon.set({ ++ width: iconSize, ++ height: iconSize, ++ x_align: Clutter.ActorAlign.CENTER, ++ y_align: Clutter.ActorAlign.CENTER ++ }); ++ ++ let iconBin = new St.Widget({ ++ layout_manager: new Clutter.BinLayout() ++ }); ++ iconBin.add_actor(icon); ++ button.add_actor(iconBin); ++ ++ this._icons.push(icon); ++ ++ button.connect('button-release-event', (actor, event) => { ++ icon.click(event); ++ }); ++ button.connect('key-press-event', (actor, event) => { ++ icon.click(event); ++ }); ++ ++ icon.connect('destroy', () => { ++ button.destroy(); ++ }); ++ ++ let role = wmClass || `${icon}`; ++ Main.panel.addToStatusArea(role, button); ++ } ++ ++ _onTrayIconRemoved(o, icon) { ++ let parent = icon.get_parent(); ++ parent.destroy(); ++ this._icons.splice(this._icons.indexOf(icon), 1); ++ } ++ ++ enable() { ++ this._tray = new Shell.TrayManager(); ++ this._tray.connect('tray-icon-added', ++ this._onTrayIconAdded.bind(this)); ++ this._tray.connect('tray-icon-removed', ++ this._onTrayIconRemoved.bind(this)); ++ this._tray.manage_screen(Main.panel.actor); ++ } ++ ++ disable() { ++ this._icons.forEach(icon => icon.get_parent().destroy()); ++ this._icons = []; ++ ++ this._tray = null; ++ System.gc(); // force finalizing tray to unmanage screen ++ } ++} ++ ++function init() { ++ return new SysTray(); ++} +diff --git a/extensions/top-icons/meson.build b/extensions/top-icons/meson.build +new file mode 100644 +index 00000000..48504f63 +--- /dev/null ++++ b/extensions/top-icons/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/top-icons/metadata.json.in b/extensions/top-icons/metadata.json.in +new file mode 100644 +index 00000000..f1e2436f +--- /dev/null ++++ b/extensions/top-icons/metadata.json.in +@@ -0,0 +1,10 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Top Icons", ++"description": "Shows legacy tray icons on top", ++"shell-version": [ "@shell_current@" ], ++"url": "http://94.247.144.115/repo/topicons/" ++} +diff --git a/extensions/top-icons/stylesheet.css b/extensions/top-icons/stylesheet.css +new file mode 100644 +index 00000000..25134b65 +--- /dev/null ++++ b/extensions/top-icons/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index b987f2d4..6050c32f 100644 +--- a/meson.build ++++ b/meson.build +@@ -50,6 +50,7 @@ all_extensions = default_extensions + all_extensions += [ + 'auto-move-windows', + 'native-window-placement', ++ 'top-icons', + 'user-theme' + ] + +-- +2.38.1 + + +From b99f1a2ead84c4fe494a387a032715f2973fbfa7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 20 May 2015 18:05:41 +0200 +Subject: [PATCH 02/11] Add dash-to-dock extension + +--- + extensions/dash-to-dock/Settings.ui | 3335 +++++++++++++++++ + extensions/dash-to-dock/appIconIndicators.js | 1102 ++++++ + extensions/dash-to-dock/appIcons.js | 1172 ++++++ + extensions/dash-to-dock/dash.js | 1171 ++++++ + extensions/dash-to-dock/docking.js | 1853 +++++++++ + extensions/dash-to-dock/extension.js | 23 + + extensions/dash-to-dock/intellihide.js | 321 ++ + extensions/dash-to-dock/launcherAPI.js | 239 ++ + extensions/dash-to-dock/media/glossy.svg | 139 + + .../media/highlight_stacked_bg.svg | 82 + + .../media/highlight_stacked_bg_h.svg | 82 + + extensions/dash-to-dock/media/logo.svg | 528 +++ + extensions/dash-to-dock/meson.build | 23 + + extensions/dash-to-dock/metadata.json.in | 12 + + ....shell.extensions.dash-to-dock.gschema.xml | 540 +++ + extensions/dash-to-dock/prefs.js | 861 +++++ + extensions/dash-to-dock/stylesheet.css | 175 + + extensions/dash-to-dock/theming.js | 569 +++ + extensions/dash-to-dock/utils.js | 258 ++ + extensions/dash-to-dock/windowPreview.js | 578 +++ + meson.build | 1 + + 21 files changed, 13064 insertions(+) + create mode 100644 extensions/dash-to-dock/Settings.ui + create mode 100644 extensions/dash-to-dock/appIconIndicators.js + create mode 100644 extensions/dash-to-dock/appIcons.js + create mode 100644 extensions/dash-to-dock/dash.js + create mode 100644 extensions/dash-to-dock/docking.js + create mode 100644 extensions/dash-to-dock/extension.js + create mode 100644 extensions/dash-to-dock/intellihide.js + create mode 100644 extensions/dash-to-dock/launcherAPI.js + create mode 100644 extensions/dash-to-dock/media/glossy.svg + create mode 100644 extensions/dash-to-dock/media/highlight_stacked_bg.svg + create mode 100644 extensions/dash-to-dock/media/highlight_stacked_bg_h.svg + create mode 100644 extensions/dash-to-dock/media/logo.svg + create mode 100644 extensions/dash-to-dock/meson.build + create mode 100644 extensions/dash-to-dock/metadata.json.in + create mode 100644 extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml + create mode 100644 extensions/dash-to-dock/prefs.js + create mode 100644 extensions/dash-to-dock/stylesheet.css + create mode 100644 extensions/dash-to-dock/theming.js + create mode 100644 extensions/dash-to-dock/utils.js + create mode 100644 extensions/dash-to-dock/windowPreview.js + +diff --git a/extensions/dash-to-dock/Settings.ui b/extensions/dash-to-dock/Settings.ui +new file mode 100644 +index 00000000..c141eff1 +--- /dev/null ++++ b/extensions/dash-to-dock/Settings.ui +@@ -0,0 +1,3335 @@ ++ ++ ++ ++ ++ ++ 1 ++ 0.050000000000000003 ++ 0.25 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ When set to minimize, double clicking minimizes all the windows of the application. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shift+Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise window ++ Minimize window ++ Launch new instance ++ Cycle through windows ++ Minimize or overview ++ Show window previews ++ Minimize or show previews ++ Focus or show previews ++ Quit ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behavior for Middle-Click. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Middle-Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise window ++ Minimize window ++ Launch new instance ++ Cycle through windows ++ Minimize or overview ++ Show window previews ++ Minimize or show previews ++ Focus or show previews ++ Quit ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behavior for Shift+Middle-Click. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shift+Middle-Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise window ++ Minimize window ++ Launch new instance ++ Cycle through windows ++ Minimize or overview ++ Show window previews ++ Minimize or show previews ++ Focus or show previews ++ Quit ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 1 ++ 0.01 ++ 0.10000000000000001 ++ ++ ++ 0.33000000000000002 ++ 1 ++ 0.01 ++ 0.10000000000000001 ++ ++ ++ 10 ++ 1 ++ 5 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ 12 ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ False ++ center ++ Enable Unity7 like glossy backlit items ++ 0 ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ ++ ++ True ++ False ++ start ++ Use dominant color ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Customize indicator style ++ fill ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 1 ++ vertical ++ 12 ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ False ++ Color ++ 0 ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ False ++ Border color ++ 0 ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ False ++ Border width ++ 0 ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ dot_border_width_adjustment ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 1 ++ 0.050000000000000003 ++ 0.25 ++ ++ ++ 16 ++ 128 ++ 1 ++ 10 ++ ++ ++ True ++ True ++ 6 ++ 6 ++ 6 ++ 6 ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Show the dock on ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ Show on all monitors. ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Position on screen ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 32 ++ ++ ++ Left ++ True ++ True ++ False ++ end ++ center ++ 0 ++ True ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ Bottom ++ True ++ True ++ False ++ center ++ 0 ++ True ++ position_left_button ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Top ++ True ++ True ++ False ++ center ++ 0 ++ bottom ++ True ++ position_left_button ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ Right ++ True ++ True ++ False ++ center ++ 0 ++ True ++ position_left_button ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Hide the dock when it obstructs a window of the current application. More refined settings are available. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Intelligent autohide ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Dock size limit ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ dock_size_adjustment ++ 0 ++ 2 ++ right ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ Panel mode: extend to the screen edge ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Icon size limit ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ icon_size_adjustment ++ 1 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ Fixed icon size: scroll to reveal other icons ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ ++ ++ True ++ False ++ Position and size ++ ++ ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show favorite applications ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show running applications ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ Isolate workspaces. ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ Isolate monitors. ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ False ++ 3 ++ 0 ++ True ++ ++ ++ True ++ False ++ Show open windows previews. ++ True ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ If disabled, these settings are accessible from gnome-tweak-tool or the extension website. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show <i>Applications</i> icon ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ Move the applications button at the beginning of the dock. ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ False ++ 3 ++ 0 ++ 0.43000000715255737 ++ True ++ ++ ++ True ++ False ++ Animate <i>Show Applications</i>. ++ True ++ ++ ++ ++ ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 1 ++ ++ ++ ++ ++ True ++ False ++ Launchers ++ ++ ++ 1 ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Enable Super+(0-9) as shortcuts to activate apps. It can also be used together with Shift and Ctrl. ++ True ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Use keyboard shortcuts to activate apps ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behaviour when clicking on the icon of a running application. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise window ++ Minimize ++ Launch new instance ++ Cycle through windows ++ Minimize or overview ++ Show window previews ++ Minimize or show previews ++ Focus or show previews ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behaviour when scrolling on the icon of an application. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Scroll action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ False ++ center ++ ++ Do nothing ++ Cycle through windows ++ Switch workspace ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ 2 ++ ++ ++ ++ ++ True ++ False ++ Behavior ++ ++ ++ 2 ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ True ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Few customizations meant to integrate the dock with the default GNOME theme. Alternatively, specific options can be enabled below. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Use built-in theme ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Save space reducing padding and border radius. ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shrink the dash ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Customize windows counter indicators ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ ++ Default ++ Dots ++ Squares ++ Dashes ++ Segmented ++ Solid ++ Ciliora ++ Metro ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Set the background color for the dash. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Customize the dash color ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Tune the dash background opacity. ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Customize opacity ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Default ++ Fixed ++ Dynamic ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Opacity ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ custom_opacity_adjustement ++ on ++ False ++ 0 ++ 0 ++ 2 ++ right ++ ++ ++ ++ ++ True ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ False ++ center ++ 12 ++ Force straight corner ++ ++ 0 ++ ++ ++ True ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ center ++ 3 ++ ++ ++ False ++ True ++ 12 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 3 ++ ++ ++ ++ ++ True ++ False ++ Appearance ++ ++ ++ 3 ++ False ++ ++ ++ ++ ++ False ++ 24 ++ 24 ++ True ++ True ++ vertical ++ 5 ++ ++ ++ ++ False ++ True ++ 10 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ <b>Dash to Dock</b> ++ True ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ ++ True ++ False ++ end ++ version: ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ start ++ ... ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ True ++ False ++ Moves the dash out of the overview transforming it in a dock ++ center ++ True ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ True ++ False ++ center ++ 5 ++ ++ ++ True ++ False ++ Created by ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ Michele (<a href="mailto:micxgx@gmail.com">micxgx@gmail.com</a>) ++ True ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 4 ++ ++ ++ ++ ++ Webpage ++ True ++ True ++ True ++ ++ center ++ none ++ https://micheleg.github.io/dash-to-dock/ ++ ++ ++ False ++ True ++ 5 ++ ++ ++ ++ ++ True ++ True ++ end ++ <span size="small">This program comes with ABSOLUTELY NO WARRANTY. ++See the <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, version 2 or later</a> for details.</span> ++ True ++ center ++ True ++ ++ ++ True ++ True ++ 6 ++ ++ ++ ++ ++ 4 ++ ++ ++ ++ ++ True ++ False ++ About ++ ++ ++ 4 ++ False ++ ++ ++ ++ ++ 1 ++ 0.01 ++ 0.10000000000000001 ++ ++ ++ 1 ++ 0.01 ++ 0.10000000000000001 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ 12 ++ ++ ++ True ++ False ++ 32 ++ ++ ++ True ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Customize minimum and maximum opacity values ++ fill ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Minimum opacity ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ min_opacity_adjustement ++ on ++ False ++ 0 ++ 0 ++ 2 ++ right ++ ++ ++ ++ ++ True ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Maximum opacity ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ max_opacity_adjustement ++ on ++ False ++ 0 ++ 0 ++ 2 ++ right ++ ++ ++ ++ ++ True ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 1000 ++ 50 ++ 250 ++ ++ ++ 10 ++ 0.25 ++ 1 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Number overlay ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Temporarily show the application numbers over the icons, corresponding to the shortcut. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show the dock if it is hidden ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ If using autohide, the dock will appear for a short time when triggering the shortcut. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ center ++ 12 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shortcut for the options above ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Syntax: <Shift>, <Ctrl>, <Alt>, <Super> ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ True ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ shortcut_time_adjustment ++ 3 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Hide timeout (s) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 1 ++ 0.050000000000000003 ++ 0.25 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Show the dock by mouse hover on the screen edge. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Autohide ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ Push to show: require pressure to show the dock ++ True ++ True ++ False ++ 0 ++ True ++ ++ ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ Enable in fullscreen mode ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Show the dock when it doesn't obstruct application windows. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Dodge windows ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ vertical ++ ++ ++ All windows ++ True ++ True ++ False ++ 12 ++ 0 ++ True ++ True ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ Only focused application's windows ++ True ++ True ++ False ++ 0 ++ True ++ True ++ all_windows_radio_button ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Only maximized windows ++ True ++ True ++ False ++ 0 ++ True ++ True ++ all_windows_radio_button ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ True ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ animation_time_adjustment ++ 3 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Animation duration (s) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ hide_timeout_adjustment ++ 3 ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ show_timeout_adjustment ++ 3 ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ 0.000 ++ pressure_threshold_adjustment ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ True ++ Hide timeout (s) ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show timeout (s) ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Pressure threshold ++ 0 ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ +diff --git a/extensions/dash-to-dock/appIconIndicators.js b/extensions/dash-to-dock/appIconIndicators.js +new file mode 100644 +index 00000000..ddff5128 +--- /dev/null ++++ b/extensions/dash-to-dock/appIconIndicators.js +@@ -0,0 +1,1102 @@ ++const Cogl = imports.gi.Cogl; ++const Cairo = imports.cairo; ++const Clutter = imports.gi.Clutter; ++const GdkPixbuf = imports.gi.GdkPixbuf ++const Gio = imports.gi.Gio; ++const Gtk = imports.gi.Gtk; ++const Pango = imports.gi.Pango; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++ ++const Util = imports.misc.util; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++ ++let tracker = Shell.WindowTracker.get_default(); ++ ++const RunningIndicatorStyle = { ++ DEFAULT: 0, ++ DOTS: 1, ++ SQUARES: 2, ++ DASHES: 3, ++ SEGMENTED: 4, ++ SOLID: 5, ++ CILIORA: 6, ++ METRO: 7 ++}; ++ ++const MAX_WINDOWS_CLASSES = 4; ++ ++ ++/* ++ * This is the main indicator class to be used. The desired bahviour is ++ * obtained by composing the desired classes below based on the settings. ++ * ++ */ ++var AppIconIndicator = class DashToDock_AppIconIndicator { ++ ++ constructor(source, settings) { ++ this._indicators = []; ++ ++ // Unity indicators always enabled for now ++ let unityIndicator = new UnityIndicator(source, settings); ++ this._indicators.push(unityIndicator); ++ ++ // Choose the style for the running indicators ++ let runningIndicator = null; ++ let runningIndicatorStyle; ++ ++ if (settings.get_boolean('apply-custom-theme' )) { ++ runningIndicatorStyle = RunningIndicatorStyle.DOTS; ++ } else { ++ runningIndicatorStyle = settings.get_enum('running-indicator-style'); ++ } ++ ++ switch (runningIndicatorStyle) { ++ case RunningIndicatorStyle.DEFAULT: ++ runningIndicator = new RunningIndicatorDefault(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.DOTS: ++ runningIndicator = new RunningIndicatorDots(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.SQUARES: ++ runningIndicator = new RunningIndicatorSquares(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.DASHES: ++ runningIndicator = new RunningIndicatorDashes(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.SEGMENTED: ++ runningIndicator = new RunningIndicatorSegmented(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.SOLID: ++ runningIndicator = new RunningIndicatorSolid(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.CILIORA: ++ runningIndicator = new RunningIndicatorCiliora(source, settings); ++ break; ++ ++ case RunningIndicatorStyle.METRO: ++ runningIndicator = new RunningIndicatorMetro(source, settings); ++ break; ++ ++ default: ++ runningIndicator = new RunningIndicatorBase(source, settings); ++ } ++ ++ this._indicators.push(runningIndicator); ++ } ++ ++ update() { ++ for (let i=0; i { ++ this._signalsHandler.destroy(); ++ }); ++ } ++ ++ update() { ++ } ++ ++ destroy() { ++ this._source.actor.disconnect(this._sourceDestroyId); ++ this._signalsHandler.destroy(); ++ } ++}; ++ ++/* ++ * A base indicator class for running style, from which all other EunningIndicators should derive, ++ * providing some basic methods, variables definitions and their update, css style classes handling. ++ * ++ */ ++var RunningIndicatorBase = class DashToDock_RunningIndicatorBase extends IndicatorBase { ++ ++ constructor(source, settings) { ++ super(source, settings) ++ ++ this._side = Utils.getPosition(this._settings); ++ this._nWindows = 0; ++ ++ this._dominantColorExtractor = new DominantColorExtractor(this._source.app); ++ ++ // These statuses take into account the workspace/monitor isolation ++ this._isFocused = false; ++ this._isRunning = false; ++ } ++ ++ update() { ++ // Limit to 1 to MAX_WINDOWS_CLASSES windows classes ++ this._nWindows = Math.min(this._source.getInterestingWindows().length, MAX_WINDOWS_CLASSES); ++ ++ // We need to check the number of windows, as the focus might be ++ // happening on another monitor if using isolation ++ if (tracker.focus_app == this._source.app && this._nWindows > 0) ++ this._isFocused = true; ++ else ++ this._isFocused = false; ++ ++ // In the case of workspace isolation, we need to hide the dots of apps with ++ // no windows in the current workspace ++ if (this._source.app.state != Shell.AppState.STOPPED && this._nWindows > 0) ++ this._isRunning = true; ++ else ++ this._isRunning = false; ++ ++ this._updateCounterClass(); ++ this._updateFocusClass(); ++ this._updateDefaultDot(); ++ } ++ ++ _updateCounterClass() { ++ for (let i = 1; i <= MAX_WINDOWS_CLASSES; i++) { ++ let className = 'running' + i; ++ if (i != this._nWindows) ++ this._source.actor.remove_style_class_name(className); ++ else ++ this._source.actor.add_style_class_name(className); ++ } ++ } ++ ++ _updateFocusClass() { ++ if (this._isFocused) ++ this._source.actor.add_style_class_name('focused'); ++ else ++ this._source.actor.remove_style_class_name('focused'); ++ } ++ ++ _updateDefaultDot() { ++ if (this._isRunning) ++ this._source._dot.show(); ++ else ++ this._source._dot.hide(); ++ } ++ ++ _hideDefaultDot() { ++ // I use opacity to hide the default dot because the show/hide function ++ // are used by the parent class. ++ this._source._dot.opacity = 0; ++ } ++ ++ _restoreDefaultDot() { ++ this._source._dot.opacity = 255; ++ } ++ ++ _enableBacklight() { ++ ++ let colorPalette = this._dominantColorExtractor._getColorPalette(); ++ ++ // Fallback ++ if (colorPalette === null) { ++ this._source._iconContainer.set_style( ++ 'border-radius: 5px;' + ++ 'background-gradient-direction: vertical;' + ++ 'background-gradient-start: #e0e0e0;' + ++ 'background-gradient-end: darkgray;' ++ ); ++ ++ return; ++ } ++ ++ this._source._iconContainer.set_style( ++ 'border-radius: 5px;' + ++ 'background-gradient-direction: vertical;' + ++ 'background-gradient-start: ' + colorPalette.original + ';' + ++ 'background-gradient-end: ' + colorPalette.darker + ';' ++ ); ++ ++ } ++ ++ _disableBacklight() { ++ this._source._iconContainer.set_style(null); ++ } ++ ++ destroy() { ++ this._disableBacklight(); ++ // Remove glossy background if the children still exists ++ if (this._source._iconContainer.get_children().length > 1) ++ this._source._iconContainer.get_children()[1].set_style(null); ++ this._restoreDefaultDot(); ++ ++ super.destroy(); ++ } ++}; ++ ++// We add a css class so third parties themes can limit their indicaor customization ++// to the case we do nothing ++var RunningIndicatorDefault = class DashToDock_RunningIndicatorDefault extends RunningIndicatorBase { ++ ++ constructor(source, settings) { ++ super(source, settings); ++ this._source.actor.add_style_class_name('default'); ++ } ++ ++ destory() { ++ this._source.actor.remove_style_class_name('default'); ++ super.destroy(); ++ } ++}; ++ ++var RunningIndicatorDots = class DashToDock_RunningIndicatorDots extends RunningIndicatorBase { ++ ++ constructor(source, settings) { ++ super(source, settings) ++ ++ this._hideDefaultDot(); ++ ++ this._area = new St.DrawingArea({x_expand: true, y_expand: true}); ++ ++ // We draw for the bottom case and rotate the canvas for other placements ++ //set center of rotatoins to the center ++ this._area.set_pivot_point(0.5, 0.5); ++ // prepare transformation matrix ++ let m = new Cogl.Matrix(); ++ m.init_identity(); ++ ++ switch (this._side) { ++ case St.Side.TOP: ++ m.xx = -1; ++ m.rotate(180, 0, 0, 1); ++ break ++ ++ case St.Side.BOTTOM: ++ // nothing ++ break; ++ ++ case St.Side.LEFT: ++ m.yy = -1; ++ m.rotate(90, 0, 0, 1); ++ break; ++ ++ case St.Side.RIGHT: ++ m.rotate(-90, 0, 0, 1); ++ break ++ } ++ ++ this._area.set_transform(m); ++ ++ this._area.connect('repaint', this._updateIndicator.bind(this)); ++ this._source._iconContainer.add_child(this._area); ++ ++ let keys = ['custom-theme-running-dots-color', ++ 'custom-theme-running-dots-border-color', ++ 'custom-theme-running-dots-border-width', ++ 'custom-theme-customize-running-dots', ++ 'unity-backlit-items', ++ 'running-indicator-dominant-color']; ++ ++ keys.forEach(function(key) { ++ this._signalsHandler.add([ ++ this._settings, ++ 'changed::' + key, ++ this.update.bind(this) ++ ]); ++ }, this); ++ ++ // Apply glossy background ++ // TODO: move to enable/disableBacklit to apply itonly to the running apps? ++ // TODO: move to css class for theming support ++ this._glossyBackgroundStyle = 'background-image: url(\'' + Me.path + '/media/glossy.svg\');' + ++ 'background-size: contain;'; ++ } ++ ++ update() { ++ super.update(); ++ ++ // Enable / Disable the backlight of running apps ++ if (!this._settings.get_boolean('apply-custom-theme') && this._settings.get_boolean('unity-backlit-items')) { ++ this._source._iconContainer.get_children()[1].set_style(this._glossyBackgroundStyle); ++ if (this._isRunning) ++ this._enableBacklight(); ++ else ++ this._disableBacklight(); ++ } else { ++ this._disableBacklight(); ++ this._source._iconContainer.get_children()[1].set_style(null); ++ } ++ ++ if (this._area) ++ this._area.queue_repaint(); ++ } ++ ++ _computeStyle() { ++ ++ let [width, height] = this._area.get_surface_size(); ++ this._width = height; ++ this._height = width; ++ ++ // By defaut re-use the style - background color, and border width and color - ++ // of the default dot ++ let themeNode = this._source._dot.get_theme_node(); ++ this._borderColor = themeNode.get_border_color(this._side); ++ this._borderWidth = themeNode.get_border_width(this._side); ++ this._bodyColor = themeNode.get_background_color(); ++ ++ if (!this._settings.get_boolean('apply-custom-theme')) { ++ // Adjust for the backlit case ++ if (this._settings.get_boolean('unity-backlit-items')) { ++ // Use dominant color for dots too if the backlit is enables ++ let colorPalette = this._dominantColorExtractor._getColorPalette(); ++ ++ // Slightly adjust the styling ++ this._borderWidth = 2; ++ ++ if (colorPalette !== null) { ++ this._borderColor = Clutter.color_from_string(colorPalette.lighter)[1] ; ++ this._bodyColor = Clutter.color_from_string(colorPalette.darker)[1]; ++ } else { ++ // Fallback ++ this._borderColor = Clutter.color_from_string('white')[1]; ++ this._bodyColor = Clutter.color_from_string('gray')[1]; ++ } ++ } ++ ++ // Apply dominant color if requested ++ if (this._settings.get_boolean('running-indicator-dominant-color')) { ++ let colorPalette = this._dominantColorExtractor._getColorPalette(); ++ if (colorPalette !== null) { ++ this._bodyColor = Clutter.color_from_string(colorPalette.original)[1]; ++ } ++ } ++ ++ // Finally, use customize style if requested ++ if (this._settings.get_boolean('custom-theme-customize-running-dots')) { ++ this._borderColor = Clutter.color_from_string(this._settings.get_string('custom-theme-running-dots-border-color'))[1]; ++ this._borderWidth = this._settings.get_int('custom-theme-running-dots-border-width'); ++ this._bodyColor = Clutter.color_from_string(this._settings.get_string('custom-theme-running-dots-color'))[1]; ++ } ++ } ++ ++ // Define the radius as an arbitrary size, but keep large enough to account ++ // for the drawing of the border. ++ this._radius = Math.max(this._width/22, this._borderWidth/2); ++ this._padding = 0; // distance from the margin ++ this._spacing = this._radius + this._borderWidth; // separation between the dots ++ } ++ ++ _updateIndicator() { ++ ++ let area = this._area; ++ let cr = this._area.get_context(); ++ ++ this._computeStyle(); ++ this._drawIndicator(cr); ++ cr.$dispose(); ++ } ++ ++ _drawIndicator(cr) { ++ // Draw the required numbers of dots ++ let n = this._nWindows; ++ ++ cr.setLineWidth(this._borderWidth); ++ Clutter.cairo_set_source_color(cr, this._borderColor); ++ ++ // draw for the bottom case: ++ cr.translate((this._width - (2*n)*this._radius - (n-1)*this._spacing)/2, this._height - this._padding); ++ for (let i = 0; i < n; i++) { ++ cr.newSubPath(); ++ cr.arc((2*i+1)*this._radius + i*this._spacing, -this._radius - this._borderWidth/2, this._radius, 0, 2*Math.PI); ++ } ++ ++ cr.strokePreserve(); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.fill(); ++ } ++ ++ destroy() { ++ this._area.destroy(); ++ super.destroy(); ++ } ++}; ++ ++// Adapted from dash-to-panel by Jason DeRose ++// https://github.com/jderose9/dash-to-panel ++var RunningIndicatorCiliora = class DashToDock_RunningIndicatorCiliora extends RunningIndicatorDots { ++ ++ _drawIndicator(cr) { ++ if (this._isRunning) { ++ ++ let size = Math.max(this._width/20, this._borderWidth); ++ let spacing = size; // separation between the dots ++ let lineLength = this._width - (size*(this._nWindows-1)) - (spacing*(this._nWindows-1)); ++ let padding = this._borderWidth; ++ // For the backlit case here we don't want the outer border visible ++ if (this._settings.get_boolean('unity-backlit-items') && !this._settings.get_boolean('custom-theme-customize-running-dots')) ++ padding = 0; ++ let yOffset = this._height - padding - size; ++ ++ cr.setLineWidth(this._borderWidth); ++ Clutter.cairo_set_source_color(cr, this._borderColor); ++ ++ cr.translate(0, yOffset); ++ cr.newSubPath(); ++ cr.rectangle(0, 0, lineLength, size); ++ for (let i = 1; i < this._nWindows; i++) { ++ cr.newSubPath(); ++ cr.rectangle(lineLength + (i*spacing) + ((i-1)*size), 0, size, size); ++ } ++ ++ cr.strokePreserve(); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.fill(); ++ } ++ } ++}; ++ ++// Adapted from dash-to-panel by Jason DeRose ++// https://github.com/jderose9/dash-to-panel ++var RunningIndicatorSegmented = class DashToDock_RunningIndicatorSegmented extends RunningIndicatorDots { ++ ++ _drawIndicator(cr) { ++ if (this._isRunning) { ++ let size = Math.max(this._width/20, this._borderWidth); ++ let spacing = Math.ceil(this._width/18); // separation between the dots ++ let dashLength = Math.ceil((this._width - ((this._nWindows-1)*spacing))/this._nWindows); ++ let lineLength = this._width - (size*(this._nWindows-1)) - (spacing*(this._nWindows-1)); ++ let padding = this._borderWidth; ++ // For the backlit case here we don't want the outer border visible ++ if (this._settings.get_boolean('unity-backlit-items') && !this._settings.get_boolean('custom-theme-customize-running-dots')) ++ padding = 0; ++ let yOffset = this._height - padding - size; ++ ++ cr.setLineWidth(this._borderWidth); ++ Clutter.cairo_set_source_color(cr, this._borderColor); ++ ++ cr.translate(0, yOffset); ++ for (let i = 0; i < this._nWindows; i++) { ++ cr.newSubPath(); ++ cr.rectangle(i*dashLength + i*spacing, 0, dashLength, size); ++ } ++ ++ cr.strokePreserve(); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.fill() ++ } ++ } ++}; ++ ++// Adapted from dash-to-panel by Jason DeRose ++// https://github.com/jderose9/dash-to-panel ++var RunningIndicatorSolid = class DashToDock_RunningIndicatorSolid extends RunningIndicatorDots { ++ ++ _drawIndicator(cr) { ++ if (this._isRunning) { ++ ++ let size = Math.max(this._width/20, this._borderWidth); ++ let padding = this._borderWidth; ++ // For the backlit case here we don't want the outer border visible ++ if (this._settings.get_boolean('unity-backlit-items') && !this._settings.get_boolean('custom-theme-customize-running-dots')) ++ padding = 0; ++ let yOffset = this._height - padding - size; ++ ++ cr.setLineWidth(this._borderWidth); ++ Clutter.cairo_set_source_color(cr, this._borderColor); ++ ++ cr.translate(0, yOffset); ++ cr.newSubPath(); ++ cr.rectangle(0, 0, this._width, size); ++ ++ cr.strokePreserve(); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.fill(); ++ ++ } ++ } ++}; ++ ++// Adapted from dash-to-panel by Jason DeRose ++// https://github.com/jderose9/dash-to-panel ++var RunningIndicatorSquares = class DashToDock_RunningIndicatorSquares extends RunningIndicatorDots { ++ ++ _drawIndicator(cr) { ++ if (this._isRunning) { ++ let size = Math.max(this._width/11, this._borderWidth); ++ let padding = this._borderWidth; ++ let spacing = Math.ceil(this._width/18); // separation between the dots ++ let yOffset = this._height - padding - size; ++ ++ cr.setLineWidth(this._borderWidth); ++ Clutter.cairo_set_source_color(cr, this._borderColor); ++ ++ cr.translate(Math.floor((this._width - this._nWindows*size - (this._nWindows-1)*spacing)/2), yOffset); ++ for (let i = 0; i < this._nWindows; i++) { ++ cr.newSubPath(); ++ cr.rectangle(i*size + i*spacing, 0, size, size); ++ } ++ cr.strokePreserve(); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.fill(); ++ } ++ } ++} ++ ++// Adapted from dash-to-panel by Jason DeRose ++// https://github.com/jderose9/dash-to-panel ++var RunningIndicatorDashes = class DashToDock_RunningIndicatorDashes extends RunningIndicatorDots { ++ ++ _drawIndicator(cr) { ++ if (this._isRunning) { ++ let size = Math.max(this._width/20, this._borderWidth); ++ let padding = this._borderWidth; ++ let spacing = Math.ceil(this._width/18); // separation between the dots ++ let dashLength = Math.floor(this._width/4) - spacing; ++ let yOffset = this._height - padding - size; ++ ++ cr.setLineWidth(this._borderWidth); ++ Clutter.cairo_set_source_color(cr, this._borderColor); ++ ++ cr.translate(Math.floor((this._width - this._nWindows*dashLength - (this._nWindows-1)*spacing)/2), yOffset); ++ for (let i = 0; i < this._nWindows; i++) { ++ cr.newSubPath(); ++ cr.rectangle(i*dashLength + i*spacing, 0, dashLength, size); ++ } ++ ++ cr.strokePreserve(); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.fill(); ++ } ++ } ++} ++ ++// Adapted from dash-to-panel by Jason DeRose ++// https://github.com/jderose9/dash-to-panel ++var RunningIndicatorMetro = class DashToDock_RunningIndicatorMetro extends RunningIndicatorDots { ++ ++ constructor(source, settings) { ++ super(source, settings); ++ this._source.actor.add_style_class_name('metro'); ++ } ++ ++ destroy() { ++ this._source.actor.remove_style_class_name('metro'); ++ super.destroy(); ++ } ++ ++ _drawIndicator(cr) { ++ if (this._isRunning) { ++ let size = Math.max(this._width/20, this._borderWidth); ++ let padding = 0; ++ // For the backlit case here we don't want the outer border visible ++ if (this._settings.get_boolean('unity-backlit-items') && !this._settings.get_boolean('custom-theme-customize-running-dots')) ++ padding = 0; ++ let yOffset = this._height - padding - size; ++ ++ let n = this._nWindows; ++ if(n <= 1) { ++ cr.translate(0, yOffset); ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.newSubPath(); ++ cr.rectangle(0, 0, this._width, size); ++ cr.fill(); ++ } else { ++ let blackenedLength = (1/48)*this._width; // need to scale with the SVG for the stacked highlight ++ let darkenedLength = this._isFocused ? (2/48)*this._width : (10/48)*this._width; ++ let blackenedColor = this._bodyColor.shade(.3); ++ let darkenedColor = this._bodyColor.shade(.7); ++ ++ cr.translate(0, yOffset); ++ ++ Clutter.cairo_set_source_color(cr, this._bodyColor); ++ cr.newSubPath(); ++ cr.rectangle(0, 0, this._width - darkenedLength - blackenedLength, size); ++ cr.fill(); ++ Clutter.cairo_set_source_color(cr, blackenedColor); ++ cr.newSubPath(); ++ cr.rectangle(this._width - darkenedLength - blackenedLength, 0, 1, size); ++ cr.fill(); ++ Clutter.cairo_set_source_color(cr, darkenedColor); ++ cr.newSubPath(); ++ cr.rectangle(this._width - darkenedLength, 0, darkenedLength, size); ++ cr.fill(); ++ } ++ } ++ } ++} ++ ++/* ++ * Unity like notification and progress indicators ++ */ ++var UnityIndicator = class DashToDock_UnityIndicator extends IndicatorBase { ++ ++ constructor(source, settings) { ++ ++ super(source, settings); ++ ++ this._notificationBadgeLabel = new St.Label(); ++ this._notificationBadgeBin = new St.Bin({ ++ child: this._notificationBadgeLabel, ++ x_align: St.Align.END, y_align: St.Align.START, ++ x_expand: true, y_expand: true ++ }); ++ this._notificationBadgeLabel.add_style_class_name('notification-badge'); ++ this._notificationBadgeCount = 0; ++ this._notificationBadgeBin.hide(); ++ ++ this._source._iconContainer.add_child(this._notificationBadgeBin); ++ this._source._iconContainer.connect('allocation-changed', this.updateNotificationBadge.bind(this)); ++ ++ this._remoteEntries = []; ++ this._source.remoteModel.lookupById(this._source.app.id).forEach( ++ (entry) => { ++ this.insertEntryRemote(entry); ++ } ++ ); ++ ++ this._signalsHandler.add([ ++ this._source.remoteModel, ++ 'entry-added', ++ this._onLauncherEntryRemoteAdded.bind(this) ++ ], [ ++ this._source.remoteModel, ++ 'entry-removed', ++ this._onLauncherEntryRemoteRemoved.bind(this) ++ ]) ++ } ++ ++ _onLauncherEntryRemoteAdded(remoteModel, entry) { ++ if (!entry || !entry.appId()) ++ return; ++ if (this._source && this._source.app && this._source.app.id == entry.appId()) { ++ this.insertEntryRemote(entry); ++ } ++ } ++ ++ _onLauncherEntryRemoteRemoved(remoteModel, entry) { ++ if (!entry || !entry.appId()) ++ return; ++ ++ if (this._source && this._source.app && this._source.app.id == entry.appId()) { ++ this.removeEntryRemote(entry); ++ } ++ } ++ ++ updateNotificationBadge() { ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ let [minWidth, natWidth] = this._source._iconContainer.get_preferred_width(-1); ++ let logicalNatWidth = natWidth / scaleFactor; ++ let font_size = Math.max(10, Math.round(logicalNatWidth / 5)); ++ let margin_left = Math.round(logicalNatWidth / 4); ++ ++ this._notificationBadgeLabel.set_style( ++ 'font-size: ' + font_size + 'px;' + ++ 'margin-left: ' + margin_left + 'px;' ++ ); ++ ++ this._notificationBadgeBin.width = Math.round(logicalNatWidth - margin_left); ++ this._notificationBadgeLabel.clutter_text.ellipsize = Pango.EllipsizeMode.MIDDLE; ++ } ++ ++ _notificationBadgeCountToText(count) { ++ if (count <= 9999) { ++ return count.toString(); ++ } else if (count < 1e5) { ++ let thousands = count / 1e3; ++ return thousands.toFixed(1).toString() + "k"; ++ } else if (count < 1e6) { ++ let thousands = count / 1e3; ++ return thousands.toFixed(0).toString() + "k"; ++ } else if (count < 1e8) { ++ let millions = count / 1e6; ++ return millions.toFixed(1).toString() + "M"; ++ } else if (count < 1e9) { ++ let millions = count / 1e6; ++ return millions.toFixed(0).toString() + "M"; ++ } else { ++ let billions = count / 1e9; ++ return billions.toFixed(1).toString() + "B"; ++ } ++ } ++ ++ setNotificationBadge(count) { ++ this._notificationBadgeCount = count; ++ let text = this._notificationBadgeCountToText(count); ++ this._notificationBadgeLabel.set_text(text); ++ } ++ ++ toggleNotificationBadge(activate) { ++ if (activate && this._notificationBadgeCount > 0) { ++ this.updateNotificationBadge(); ++ this._notificationBadgeBin.show(); ++ } ++ else ++ this._notificationBadgeBin.hide(); ++ } ++ ++ _showProgressOverlay() { ++ if (this._progressOverlayArea) { ++ this._updateProgressOverlay(); ++ return; ++ } ++ ++ this._progressOverlayArea = new St.DrawingArea({x_expand: true, y_expand: true}); ++ this._progressOverlayArea.connect('repaint', () => { ++ this._drawProgressOverlay(this._progressOverlayArea); ++ }); ++ ++ this._source._iconContainer.add_child(this._progressOverlayArea); ++ this._updateProgressOverlay(); ++ } ++ ++ _hideProgressOverlay() { ++ if (this._progressOverlayArea) ++ this._progressOverlayArea.destroy(); ++ this._progressOverlayArea = null; ++ } ++ ++ _updateProgressOverlay() { ++ if (this._progressOverlayArea) ++ this._progressOverlayArea.queue_repaint(); ++ } ++ ++ _drawProgressOverlay(area) { ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ let [surfaceWidth, surfaceHeight] = area.get_surface_size(); ++ let cr = area.get_context(); ++ ++ let iconSize = this._source.icon.iconSize * scaleFactor; ++ ++ let x = Math.floor((surfaceWidth - iconSize) / 2); ++ let y = Math.floor((surfaceHeight - iconSize) / 2); ++ ++ let lineWidth = Math.floor(1.0 * scaleFactor); ++ let padding = Math.floor(iconSize * 0.05); ++ let width = iconSize - 2.0*padding; ++ let height = Math.floor(Math.min(18.0*scaleFactor, 0.20*iconSize)); ++ x += padding; ++ y += iconSize - height - padding; ++ ++ cr.setLineWidth(lineWidth); ++ ++ // Draw the outer stroke ++ let stroke = new Cairo.LinearGradient(0, y, 0, y + height); ++ let fill = null; ++ stroke.addColorStopRGBA(0.5, 0.5, 0.5, 0.5, 0.1); ++ stroke.addColorStopRGBA(0.9, 0.8, 0.8, 0.8, 0.4); ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill); ++ ++ // Draw the background ++ x += lineWidth; ++ y += lineWidth; ++ width -= 2.0*lineWidth; ++ height -= 2.0*lineWidth; ++ ++ stroke = Cairo.SolidPattern.createRGBA(0.20, 0.20, 0.20, 0.9); ++ fill = new Cairo.LinearGradient(0, y, 0, y + height); ++ fill.addColorStopRGBA(0.4, 0.25, 0.25, 0.25, 1.0); ++ fill.addColorStopRGBA(0.9, 0.35, 0.35, 0.35, 1.0); ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill); ++ ++ // Draw the finished bar ++ x += lineWidth; ++ y += lineWidth; ++ width -= 2.0*lineWidth; ++ height -= 2.0*lineWidth; ++ ++ let finishedWidth = Math.ceil(this._progress * width); ++ stroke = Cairo.SolidPattern.createRGBA(0.8, 0.8, 0.8, 1.0); ++ fill = Cairo.SolidPattern.createRGBA(0.9, 0.9, 0.9, 1.0); ++ ++ if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0 + width - finishedWidth, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill); ++ else ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill); ++ ++ cr.$dispose(); ++ } ++ ++ setProgress(progress) { ++ this._progress = Math.min(Math.max(progress, 0.0), 1.0); ++ this._updateProgressOverlay(); ++ } ++ ++ toggleProgressOverlay(activate) { ++ if (activate) { ++ this._showProgressOverlay(); ++ } ++ else { ++ this._hideProgressOverlay(); ++ } ++ } ++ ++ insertEntryRemote(remote) { ++ if (!remote || this._remoteEntries.indexOf(remote) !== -1) ++ return; ++ ++ this._remoteEntries.push(remote); ++ this._selectEntryRemote(remote); ++ } ++ ++ removeEntryRemote(remote) { ++ if (!remote || this._remoteEntries.indexOf(remote) == -1) ++ return; ++ ++ this._remoteEntries.splice(this._remoteEntries.indexOf(remote), 1); ++ ++ if (this._remoteEntries.length > 0) { ++ this._selectEntryRemote(this._remoteEntries[this._remoteEntries.length-1]); ++ } else { ++ this.setNotificationBadge(0); ++ this.toggleNotificationBadge(false); ++ this.setProgress(0); ++ this.toggleProgressOverlay(false); ++ } ++ } ++ ++ _selectEntryRemote(remote) { ++ if (!remote) ++ return; ++ ++ this._signalsHandler.removeWithLabel('entry-remotes'); ++ ++ this._signalsHandler.addWithLabel('entry-remotes', ++ [ ++ remote, ++ 'count-changed', ++ (remote, value) => { ++ this.setNotificationBadge(value); ++ } ++ ], [ ++ remote, ++ 'count-visible-changed', ++ (remote, value) => { ++ this.toggleNotificationBadge(value); ++ } ++ ], [ ++ remote, ++ 'progress-changed', ++ (remote, value) => { ++ this.setProgress(value); ++ } ++ ], [ ++ remote, ++ 'progress-visible-changed', ++ (remote, value) => { ++ this.toggleProgressOverlay(value); ++ } ++ ]); ++ ++ this.setNotificationBadge(remote.count()); ++ this.toggleNotificationBadge(remote.countVisible()); ++ this.setProgress(remote.progress()); ++ this.toggleProgressOverlay(remote.progressVisible()); ++ } ++} ++ ++ ++// We need an icons theme object, this is the only way I managed to get ++// pixel buffers that can be used for calculating the backlight color ++let themeLoader = null; ++ ++// Global icon cache. Used for Unity7 styling. ++let iconCacheMap = new Map(); ++// Max number of items to store ++// We don't expect to ever reach this number, but let's put an hard limit to avoid ++// even the remote possibility of the cached items to grow indefinitely. ++const MAX_CACHED_ITEMS = 1000; ++// When the size exceed it, the oldest 'n' ones are deleted ++const BATCH_SIZE_TO_DELETE = 50; ++// The icon size used to extract the dominant color ++const DOMINANT_COLOR_ICON_SIZE = 64; ++ ++// Compute dominant color frim the app icon. ++// The color is cached for efficiency. ++var DominantColorExtractor = class DashToDock_DominantColorExtractor { ++ ++ constructor(app) { ++ this._app = app; ++ } ++ ++ /** ++ * Try to get the pixel buffer for the current icon, if not fail gracefully ++ */ ++ _getIconPixBuf() { ++ let iconTexture = this._app.create_icon_texture(16); ++ ++ if (themeLoader === null) { ++ let ifaceSettings = new Gio.Settings({ schema: "org.gnome.desktop.interface" }); ++ ++ themeLoader = new Gtk.IconTheme(), ++ themeLoader.set_custom_theme(ifaceSettings.get_string('icon-theme')); // Make sure the correct theme is loaded ++ } ++ ++ // Unable to load the icon texture, use fallback ++ if (iconTexture instanceof St.Icon === false) { ++ return null; ++ } ++ ++ iconTexture = iconTexture.get_gicon(); ++ ++ // Unable to load the icon texture, use fallback ++ if (iconTexture === null) { ++ return null; ++ } ++ ++ if (iconTexture instanceof Gio.FileIcon) { ++ // Use GdkPixBuf to load the pixel buffer from the provided file path ++ return GdkPixbuf.Pixbuf.new_from_file(iconTexture.get_file().get_path()); ++ } ++ ++ // Get the pixel buffer from the icon theme ++ let icon_info = themeLoader.lookup_icon(iconTexture.get_names()[0], DOMINANT_COLOR_ICON_SIZE, 0); ++ if (icon_info !== null) ++ return icon_info.load_icon(); ++ else ++ return null; ++ } ++ ++ /** ++ * The backlight color choosing algorithm was mostly ported to javascript from the ++ * Unity7 C++ source of Canonicals: ++ * https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp ++ * so it more or less works the same way. ++ */ ++ _getColorPalette() { ++ if (iconCacheMap.get(this._app.get_id())) { ++ // We already know the answer ++ return iconCacheMap.get(this._app.get_id()); ++ } ++ ++ let pixBuf = this._getIconPixBuf(); ++ if (pixBuf == null) ++ return null; ++ ++ let pixels = pixBuf.get_pixels(), ++ offset = 0; ++ ++ let total = 0, ++ rTotal = 0, ++ gTotal = 0, ++ bTotal = 0; ++ ++ let resample_y = 1, ++ resample_x = 1; ++ ++ // Resampling of large icons ++ // We resample icons larger than twice the desired size, as the resampling ++ // to a size s ++ // DOMINANT_COLOR_ICON_SIZE < s < 2*DOMINANT_COLOR_ICON_SIZE, ++ // most of the case exactly DOMINANT_COLOR_ICON_SIZE as the icon size is tipycally ++ // a multiple of it. ++ let width = pixBuf.get_width(); ++ let height = pixBuf.get_height(); ++ ++ // Resample ++ if (height >= 2* DOMINANT_COLOR_ICON_SIZE) ++ resample_y = Math.floor(height/DOMINANT_COLOR_ICON_SIZE); ++ ++ if (width >= 2* DOMINANT_COLOR_ICON_SIZE) ++ resample_x = Math.floor(width/DOMINANT_COLOR_ICON_SIZE); ++ ++ if (resample_x !==1 || resample_y !== 1) ++ pixels = this._resamplePixels(pixels, resample_x, resample_y); ++ ++ // computing the limit outside the for (where it would be repeated at each iteration) ++ // for performance reasons ++ let limit = pixels.length; ++ for (let offset = 0; offset < limit; offset+=4) { ++ let r = pixels[offset], ++ g = pixels[offset + 1], ++ b = pixels[offset + 2], ++ a = pixels[offset + 3]; ++ ++ let saturation = (Math.max(r,g, b) - Math.min(r,g, b)); ++ let relevance = 0.1 * 255 * 255 + 0.9 * a * saturation; ++ ++ rTotal += r * relevance; ++ gTotal += g * relevance; ++ bTotal += b * relevance; ++ ++ total += relevance; ++ } ++ ++ total = total * 255; ++ ++ let r = rTotal / total, ++ g = gTotal / total, ++ b = bTotal / total; ++ ++ let hsv = Utils.ColorUtils.RGBtoHSV(r * 255, g * 255, b * 255); ++ ++ if (hsv.s > 0.15) ++ hsv.s = 0.65; ++ hsv.v = 0.90; ++ ++ let rgb = Utils.ColorUtils.HSVtoRGB(hsv.h, hsv.s, hsv.v); ++ ++ // Cache the result. ++ let backgroundColor = { ++ lighter: Utils.ColorUtils.ColorLuminance(rgb.r, rgb.g, rgb.b, 0.2), ++ original: Utils.ColorUtils.ColorLuminance(rgb.r, rgb.g, rgb.b, 0), ++ darker: Utils.ColorUtils.ColorLuminance(rgb.r, rgb.g, rgb.b, -0.5) ++ }; ++ ++ if (iconCacheMap.size >= MAX_CACHED_ITEMS) { ++ //delete oldest cached values (which are in order of insertions) ++ let ctr=0; ++ for (let key of iconCacheMap.keys()) { ++ if (++ctr > BATCH_SIZE_TO_DELETE) ++ break; ++ iconCacheMap.delete(key); ++ } ++ } ++ ++ iconCacheMap.set(this._app.get_id(), backgroundColor); ++ ++ return backgroundColor; ++ } ++ ++ /** ++ * Downsample large icons before scanning for the backlight color to ++ * improve performance. ++ * ++ * @param pixBuf ++ * @param pixels ++ * @param resampleX ++ * @param resampleY ++ * ++ * @return []; ++ */ ++ _resamplePixels (pixels, resampleX, resampleY) { ++ let resampledPixels = []; ++ // computing the limit outside the for (where it would be repeated at each iteration) ++ // for performance reasons ++ let limit = pixels.length / (resampleX * resampleY) / 4; ++ for (let i = 0; i < limit; i++) { ++ let pixel = i * resampleX * resampleY; ++ ++ resampledPixels.push(pixels[pixel * 4]); ++ resampledPixels.push(pixels[pixel * 4 + 1]); ++ resampledPixels.push(pixels[pixel * 4 + 2]); ++ resampledPixels.push(pixels[pixel * 4 + 3]); ++ } ++ ++ return resampledPixels; ++ } ++}; +diff --git a/extensions/dash-to-dock/appIcons.js b/extensions/dash-to-dock/appIcons.js +new file mode 100644 +index 00000000..3b28304d +--- /dev/null ++++ b/extensions/dash-to-dock/appIcons.js +@@ -0,0 +1,1172 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const Clutter = imports.gi.Clutter; ++const GdkPixbuf = imports.gi.GdkPixbuf ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Gtk = imports.gi.Gtk; ++const Signals = imports.signals; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++ ++// Use __ () and N__() for the extension gettext domain, and reuse ++// the shell domain with the default _() and N_() ++const Gettext = imports.gettext.domain('dashtodock'); ++const __ = Gettext.gettext; ++const N__ = function(e) { return e }; ++ ++const AppDisplay = imports.ui.appDisplay; ++const AppFavorites = imports.ui.appFavorites; ++const Dash = imports.ui.dash; ++const DND = imports.ui.dnd; ++const IconGrid = imports.ui.iconGrid; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; ++const Util = imports.misc.util; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++const WindowPreview = Me.imports.windowPreview; ++const AppIconIndicators = Me.imports.appIconIndicators; ++ ++let tracker = Shell.WindowTracker.get_default(); ++ ++let DASH_ITEM_LABEL_SHOW_TIME = Dash.DASH_ITEM_LABEL_SHOW_TIME; ++ ++const clickAction = { ++ SKIP: 0, ++ MINIMIZE: 1, ++ LAUNCH: 2, ++ CYCLE_WINDOWS: 3, ++ MINIMIZE_OR_OVERVIEW: 4, ++ PREVIEWS: 5, ++ MINIMIZE_OR_PREVIEWS: 6, ++ FOCUS_OR_PREVIEWS: 7, ++ QUIT: 8, ++}; ++ ++const scrollAction = { ++ DO_NOTHING: 0, ++ CYCLE_WINDOWS: 1, ++ SWITCH_WORKSPACE: 2 ++}; ++ ++let recentlyClickedAppLoopId = 0; ++let recentlyClickedApp = null; ++let recentlyClickedAppWindows = null; ++let recentlyClickedAppIndex = 0; ++let recentlyClickedAppMonitor = -1; ++ ++/** ++ * Extend AppIcon ++ * ++ * - Pass settings to the constructor and bind settings changes ++ * - Apply a css class based on the number of windows of each application (#N); ++ * - Customized indicators for running applications in place of the default "dot" style which is hidden (#N); ++ * a class of the form "running#N" is applied to the AppWellIcon actor. ++ * like the original .running one. ++ * - Add a .focused style to the focused app ++ * - Customize click actions. ++ * - Update minimization animation target ++ * - Update menu if open on windows change ++ */ ++var MyAppIcon = class DashToDock_AppIcon extends AppDisplay.AppIcon { ++ ++ // settings are required inside. ++ constructor(settings, remoteModel, app, monitorIndex, iconParams) { ++ super(app, iconParams); ++ ++ // a prefix is required to avoid conflicting with the parent class variable ++ this._dtdSettings = settings; ++ this.monitorIndex = monitorIndex; ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this.remoteModel = remoteModel; ++ this._indicator = null; ++ ++ this._updateIndicatorStyle(); ++ ++ // Monitor windows-changes instead of app state. ++ // Keep using the same Id and function callback (that is extended) ++ if (this._stateChangedId > 0) { ++ this.app.disconnect(this._stateChangedId); ++ this._stateChangedId = 0; ++ } ++ ++ this._windowsChangedId = this.app.connect('windows-changed', ++ this.onWindowsChanged.bind(this)); ++ this._focusAppChangeId = tracker.connect('notify::focus-app', ++ this._onFocusAppChanged.bind(this)); ++ ++ // In Wayland sessions, this signal is needed to track the state of windows dragged ++ // from one monitor to another. As this is triggered quite often (whenever a new winow ++ // of any application opened or moved to a different desktop), ++ // we restrict this signal to the case when 'isolate-monitors' is true, ++ // and if there are at least 2 monitors. ++ if (this._dtdSettings.get_boolean('isolate-monitors') && ++ Main.layoutManager.monitors.length > 1) { ++ this._signalsHandler.removeWithLabel('isolate-monitors'); ++ this._signalsHandler.addWithLabel('isolate-monitors', [ ++ global.display, ++ 'window-entered-monitor', ++ this._onWindowEntered.bind(this) ++ ]); ++ } ++ ++ this._progressOverlayArea = null; ++ this._progress = 0; ++ ++ let keys = ['apply-custom-theme', ++ 'running-indicator-style', ++ ]; ++ ++ keys.forEach(function(key) { ++ this._signalsHandler.add([ ++ this._dtdSettings, ++ 'changed::' + key, ++ this._updateIndicatorStyle.bind(this) ++ ]); ++ }, this); ++ ++ this._dtdSettings.connect('changed::scroll-action', () => { ++ this._optionalScrollCycleWindows(); ++ }); ++ this._optionalScrollCycleWindows(); ++ ++ this._numberOverlay(); ++ ++ this._previewMenuManager = null; ++ this._previewMenu = null; ++ } ++ ++ _onDestroy() { ++ super._onDestroy(); ++ ++ // This is necessary due to an upstream bug ++ // https://bugzilla.gnome.org/show_bug.cgi?id=757556 ++ // It can be safely removed once it get solved upstrea. ++ if (this._menu) ++ this._menu.close(false); ++ ++ // Disconect global signals ++ ++ if (this._windowsChangedId > 0) ++ this.app.disconnect(this._windowsChangedId); ++ this._windowsChangedId = 0; ++ ++ if (this._focusAppChangeId > 0) { ++ tracker.disconnect(this._focusAppChangeId); ++ this._focusAppChangeId = 0; ++ } ++ ++ this._signalsHandler.destroy(); ++ ++ if (this._scrollEventHandler) ++ this.actor.disconnect(this._scrollEventHandler); ++ } ++ ++ // TOOD Rename this function ++ _updateIndicatorStyle() { ++ ++ if (this._indicator !== null) { ++ this._indicator.destroy(); ++ this._indicator = null; ++ } ++ this._indicator = new AppIconIndicators.AppIconIndicator(this, this._dtdSettings); ++ this._indicator.update(); ++ } ++ ++ _onWindowEntered(metaScreen, monitorIndex, metaWin) { ++ let app = Shell.WindowTracker.get_default().get_window_app(metaWin); ++ if (app && app.get_id() == this.app.get_id()) ++ this.onWindowsChanged(); ++ } ++ ++ _optionalScrollCycleWindows() { ++ if (this._scrollEventHandler) { ++ this.actor.disconnect(this._scrollEventHandler); ++ this._scrollEventHandler = 0; ++ } ++ ++ let isEnabled = this._dtdSettings.get_enum('scroll-action') === scrollAction.CYCLE_WINDOWS; ++ if (!isEnabled) return; ++ this._scrollEventHandler = this.actor.connect('scroll-event', ++ this.onScrollEvent.bind(this)); ++ } ++ ++ onScrollEvent(actor, event) { ++ ++ // We only activate windows of running applications, i.e. we never open new windows ++ // We check if the app is running, and that the # of windows is > 0 in ++ // case we use workspace isolation, ++ let appIsRunning = this.app.state == Shell.AppState.RUNNING ++ && this.getInterestingWindows().length > 0; ++ ++ if (!appIsRunning) ++ return false ++ ++ if (this._optionalScrollCycleWindowsDeadTimeId > 0) ++ return false; ++ else ++ this._optionalScrollCycleWindowsDeadTimeId = Mainloop.timeout_add(250, () => { ++ this._optionalScrollCycleWindowsDeadTimeId = 0; ++ }); ++ ++ let direction = null; ++ ++ switch (event.get_scroll_direction()) { ++ case Clutter.ScrollDirection.UP: ++ direction = Meta.MotionDirection.UP; ++ break; ++ case Clutter.ScrollDirection.DOWN: ++ direction = Meta.MotionDirection.DOWN; ++ break; ++ case Clutter.ScrollDirection.SMOOTH: ++ let [dx, dy] = event.get_scroll_delta(); ++ if (dy < 0) ++ direction = Meta.MotionDirection.UP; ++ else if (dy > 0) ++ direction = Meta.MotionDirection.DOWN; ++ break; ++ } ++ ++ let focusedApp = tracker.focus_app; ++ if (!Main.overview._shown) { ++ let reversed = direction === Meta.MotionDirection.UP; ++ if (this.app == focusedApp) ++ this._cycleThroughWindows(reversed); ++ else { ++ // Activate the first window ++ let windows = this.getInterestingWindows(); ++ if (windows.length > 0) { ++ let w = windows[0]; ++ Main.activateWindow(w); ++ } ++ } ++ } ++ else ++ this.app.activate(); ++ return true; ++ } ++ ++ onWindowsChanged() { ++ ++ if (this._menu && this._menu.isOpen) ++ this._menu.update(); ++ ++ this._indicator.update(); ++ this.updateIconGeometry(); ++ } ++ ++ /** ++ * Update taraget for minimization animation ++ */ ++ updateIconGeometry() { ++ // If (for unknown reason) the actor is not on the stage the reported size ++ // and position are random values, which might exceeds the integer range ++ // resulting in an error when assigned to the a rect. This is a more like ++ // a workaround to prevent flooding the system with errors. ++ if (this.actor.get_stage() == null) ++ return; ++ ++ let rect = new Meta.Rectangle(); ++ ++ [rect.x, rect.y] = this.actor.get_transformed_position(); ++ [rect.width, rect.height] = this.actor.get_transformed_size(); ++ ++ let windows = this.app.get_windows(); ++ if (this._dtdSettings.get_boolean('multi-monitor')){ ++ let monitorIndex = this.monitorIndex; ++ windows = windows.filter(function(w) { ++ return w.get_monitor() == monitorIndex; ++ }); ++ } ++ windows.forEach(function(w) { ++ w.set_icon_geometry(rect); ++ }); ++ } ++ ++ _updateRunningStyle() { ++ // The logic originally in this function has been moved to ++ // AppIconIndicatorBase._updateDefaultDot(). However it cannot be removed as ++ // it called by the parent constructor. ++ } ++ ++ popupMenu() { ++ this._removeMenuTimeout(); ++ this.actor.fake_release(); ++ this._draggable.fakeRelease(); ++ ++ if (!this._menu) { ++ this._menu = new MyAppIconMenu(this, this._dtdSettings); ++ this._menu.connect('activate-window', (menu, window) => { ++ this.activateWindow(window); ++ }); ++ this._menu.connect('open-state-changed', (menu, isPoppedUp) => { ++ if (!isPoppedUp) ++ this._onMenuPoppedDown(); ++ else { ++ // Setting the max-height is s useful if part of the menu is ++ // scrollable so the minimum height is smaller than the natural height. ++ let monitor_index = Main.layoutManager.findIndexForActor(this.actor); ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor_index); ++ let position = Utils.getPosition(this._dtdSettings); ++ this._isHorizontal = ( position == St.Side.TOP || ++ position == St.Side.BOTTOM); ++ // If horizontal also remove the height of the dash ++ let additional_margin = this._isHorizontal && !this._dtdSettings.get_boolean('dock-fixed') ? Main.overview._dash.actor.height : 0; ++ let verticalMargins = this._menu.actor.margin_top + this._menu.actor.margin_bottom; ++ // Also set a max width to the menu, so long labels (long windows title) get truncated ++ this._menu.actor.style = ('max-height: ' + Math.round(workArea.height - additional_margin - verticalMargins) + 'px;' + ++ 'max-width: 400px'); ++ } ++ }); ++ let id = Main.overview.connect('hiding', () => { ++ this._menu.close(); ++ }); ++ this._menu.actor.connect('destroy', function() { ++ Main.overview.disconnect(id); ++ }); ++ ++ this._menuManager.addMenu(this._menu); ++ } ++ ++ this.emit('menu-state-changed', true); ++ ++ this.actor.set_hover(true); ++ this._menu.popup(); ++ this._menuManager.ignoreRelease(); ++ this.emit('sync-tooltip'); ++ ++ return false; ++ } ++ ++ _onFocusAppChanged() { ++ this._indicator.update(); ++ } ++ ++ activate(button) { ++ let event = Clutter.get_current_event(); ++ let modifiers = event ? event.get_state() : 0; ++ let focusedApp = tracker.focus_app; ++ ++ // Only consider SHIFT and CONTROL as modifiers (exclude SUPER, CAPS-LOCK, etc.) ++ modifiers = modifiers & (Clutter.ModifierType.SHIFT_MASK | Clutter.ModifierType.CONTROL_MASK); ++ ++ // We don't change the CTRL-click behaviour: in such case we just chain ++ // up the parent method and return. ++ if (modifiers & Clutter.ModifierType.CONTROL_MASK) { ++ // Keep default behaviour: launch new window ++ // By calling the parent method I make it compatible ++ // with other extensions tweaking ctrl + click ++ super.activate(button); ++ return; ++ } ++ ++ // We check what type of click we have and if the modifier SHIFT is ++ // being used. We then define what buttonAction should be for this ++ // event. ++ let buttonAction = 0; ++ if (button && button == 2 ) { ++ if (modifiers & Clutter.ModifierType.SHIFT_MASK) ++ buttonAction = this._dtdSettings.get_enum('shift-middle-click-action'); ++ else ++ buttonAction = this._dtdSettings.get_enum('middle-click-action'); ++ } ++ else if (button && button == 1) { ++ if (modifiers & Clutter.ModifierType.SHIFT_MASK) ++ buttonAction = this._dtdSettings.get_enum('shift-click-action'); ++ else ++ buttonAction = this._dtdSettings.get_enum('click-action'); ++ } ++ ++ // We check if the app is running, and that the # of windows is > 0 in ++ // case we use workspace isolation. ++ let windows = this.getInterestingWindows(); ++ let appIsRunning = this.app.state == Shell.AppState.RUNNING ++ && windows.length > 0; ++ ++ // Some action modes (e.g. MINIMIZE_OR_OVERVIEW) require overview to remain open ++ // This variable keeps track of this ++ let shouldHideOverview = true; ++ ++ // We customize the action only when the application is already running ++ if (appIsRunning) { ++ switch (buttonAction) { ++ case clickAction.MINIMIZE: ++ // In overview just activate the app, unless the acion is explicitely ++ // requested with a keyboard modifier ++ if (!Main.overview._shown || modifiers){ ++ // If we have button=2 or a modifier, allow minimization even if ++ // the app is not focused ++ if (this.app == focusedApp || button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK) { ++ // minimize all windows on double click and always in the case of primary click without ++ // additional modifiers ++ let click_count = 0; ++ if (Clutter.EventType.CLUTTER_BUTTON_PRESS) ++ click_count = event.get_click_count(); ++ let all_windows = (button == 1 && ! modifiers) || click_count > 1; ++ this._minimizeWindow(all_windows); ++ } ++ else ++ this._activateAllWindows(); ++ } ++ else { ++ let w = windows[0]; ++ Main.activateWindow(w); ++ } ++ break; ++ ++ case clickAction.MINIMIZE_OR_OVERVIEW: ++ // When a single window is present, toggle minimization ++ // If only one windows is present toggle minimization, but only when trigggered with the ++ // simple click action (no modifiers, no middle click). ++ if (windows.length == 1 && !modifiers && button == 1) { ++ let w = windows[0]; ++ if (this.app == focusedApp) { ++ // Window is raised, minimize it ++ this._minimizeWindow(w); ++ } else { ++ // Window is minimized, raise it ++ Main.activateWindow(w); ++ } ++ // Launch overview when multiple windows are present ++ // TODO: only show current app windows when gnome shell API will allow it ++ } else { ++ shouldHideOverview = false; ++ Main.overview.toggle(); ++ } ++ break; ++ ++ case clickAction.CYCLE_WINDOWS: ++ if (!Main.overview._shown){ ++ if (this.app == focusedApp) ++ this._cycleThroughWindows(); ++ else { ++ // Activate the first window ++ let w = windows[0]; ++ Main.activateWindow(w); ++ } ++ } ++ else ++ this.app.activate(); ++ break; ++ ++ case clickAction.FOCUS_OR_PREVIEWS: ++ if (this.app == focusedApp && ++ (windows.length > 1 || modifiers || button != 1)) { ++ this._windowPreviews(); ++ } else { ++ // Activate the first window ++ let w = windows[0]; ++ Main.activateWindow(w); ++ } ++ break; ++ ++ case clickAction.LAUNCH: ++ this.launchNewWindow(); ++ break; ++ ++ case clickAction.PREVIEWS: ++ if (!Main.overview._shown) { ++ // If only one windows is present just switch to it, but only when trigggered with the ++ // simple click action (no modifiers, no middle click). ++ if (windows.length == 1 && !modifiers && button == 1) { ++ let w = windows[0]; ++ Main.activateWindow(w); ++ } else ++ this._windowPreviews(); ++ } ++ else { ++ this.app.activate(); ++ } ++ break; ++ ++ case clickAction.MINIMIZE_OR_PREVIEWS: ++ // When a single window is present, toggle minimization ++ // If only one windows is present toggle minimization, but only when trigggered with the ++ // simple click action (no modifiers, no middle click). ++ if (!Main.overview._shown){ ++ if (windows.length == 1 && !modifiers && button == 1) { ++ let w = windows[0]; ++ if (this.app == focusedApp) { ++ // Window is raised, minimize it ++ this._minimizeWindow(w); ++ } else { ++ // Window is minimized, raise it ++ Main.activateWindow(w); ++ } ++ } else { ++ // Launch previews when multiple windows are present ++ this._windowPreviews(); ++ } ++ } else { ++ this.app.activate(); ++ } ++ break; ++ ++ case clickAction.QUIT: ++ this.closeAllWindows(); ++ break; ++ ++ case clickAction.SKIP: ++ let w = windows[0]; ++ Main.activateWindow(w); ++ break; ++ } ++ } ++ else { ++ this.launchNewWindow(); ++ } ++ ++ // Hide overview except when action mode requires it ++ if(shouldHideOverview) { ++ Main.overview.hide(); ++ } ++ } ++ ++ shouldShowTooltip() { ++ return this.actor.hover && (!this._menu || !this._menu.isOpen) && ++ (!this._previewMenu || !this._previewMenu.isOpen); ++ } ++ ++ _windowPreviews() { ++ if (!this._previewMenu) { ++ this._previewMenuManager = new PopupMenu.PopupMenuManager(this); ++ ++ this._previewMenu = new WindowPreview.WindowPreviewMenu(this, this._dtdSettings); ++ ++ this._previewMenuManager.addMenu(this._previewMenu); ++ ++ this._previewMenu.connect('open-state-changed', (menu, isPoppedUp) => { ++ if (!isPoppedUp) ++ this._onMenuPoppedDown(); ++ }); ++ let id = Main.overview.connect('hiding', () => { ++ this._previewMenu.close(); ++ }); ++ this._previewMenu.actor.connect('destroy', function() { ++ Main.overview.disconnect(id); ++ }); ++ ++ } ++ ++ if (this._previewMenu.isOpen) ++ this._previewMenu.close(); ++ else ++ this._previewMenu.popup(); ++ ++ return false; ++ } ++ ++ // Try to do the right thing when attempting to launch a new window of an app. In ++ // particular, if the application doens't allow to launch a new window, activate ++ // the existing window instead. ++ launchNewWindow(p) { ++ let appInfo = this.app.get_app_info(); ++ let actions = appInfo.list_actions(); ++ if (this.app.can_open_new_window()) { ++ this.animateLaunch(); ++ // This is used as a workaround for a bug resulting in no new windows being opened ++ // for certain running applications when calling open_new_window(). ++ // ++ // https://bugzilla.gnome.org/show_bug.cgi?id=756844 ++ // ++ // Similar to what done when generating the popupMenu entries, if the application provides ++ // a "New Window" action, use it instead of directly requesting a new window with ++ // open_new_window(), which fails for certain application, notably Nautilus. ++ if (actions.indexOf('new-window') == -1) { ++ this.app.open_new_window(-1); ++ } ++ else { ++ let i = actions.indexOf('new-window'); ++ if (i !== -1) ++ this.app.launch_action(actions[i], global.get_current_time(), -1); ++ } ++ } ++ else { ++ // Try to manually activate the first window. Otherwise, when the app is activated by ++ // switching to a different workspace, a launch spinning icon is shown and disappers only ++ // after a timeout. ++ let windows = this.app.get_windows(); ++ if (windows.length > 0) ++ Main.activateWindow(windows[0]) ++ else ++ this.app.activate(); ++ } ++ } ++ ++ _numberOverlay() { ++ // Add label for a Hot-Key visual aid ++ this._numberOverlayLabel = new St.Label(); ++ this._numberOverlayBin = new St.Bin({ ++ child: this._numberOverlayLabel, ++ x_align: St.Align.START, y_align: St.Align.START, ++ x_expand: true, y_expand: true ++ }); ++ this._numberOverlayLabel.add_style_class_name('number-overlay'); ++ this._numberOverlayOrder = -1; ++ this._numberOverlayBin.hide(); ++ ++ this._iconContainer.add_child(this._numberOverlayBin); ++ ++ } ++ ++ updateNumberOverlay() { ++ // We apply an overall scale factor that might come from a HiDPI monitor. ++ // Clutter dimensions are in physical pixels, but CSS measures are in logical ++ // pixels, so make sure to consider the scale. ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ // Set the font size to something smaller than the whole icon so it is ++ // still visible. The border radius is large to make the shape circular ++ let [minWidth, natWidth] = this._iconContainer.get_preferred_width(-1); ++ let font_size = Math.round(Math.max(12, 0.3*natWidth) / scaleFactor); ++ let size = Math.round(font_size*1.2); ++ this._numberOverlayLabel.set_style( ++ 'font-size: ' + font_size + 'px;' + ++ 'border-radius: ' + this.icon.iconSize + 'px;' + ++ 'width: ' + size + 'px; height: ' + size +'px;' ++ ); ++ } ++ ++ setNumberOverlay(number) { ++ this._numberOverlayOrder = number; ++ this._numberOverlayLabel.set_text(number.toString()); ++ } ++ ++ toggleNumberOverlay(activate) { ++ if (activate && this._numberOverlayOrder > -1) { ++ this.updateNumberOverlay(); ++ this._numberOverlayBin.show(); ++ } ++ else ++ this._numberOverlayBin.hide(); ++ } ++ ++ _minimizeWindow(param) { ++ // Param true make all app windows minimize ++ let windows = this.getInterestingWindows(); ++ let current_workspace = global.workspace_manager.get_active_workspace(); ++ for (let i = 0; i < windows.length; i++) { ++ let w = windows[i]; ++ if (w.get_workspace() == current_workspace && w.showing_on_its_workspace()) { ++ w.minimize(); ++ // Just minimize one window. By specification it should be the ++ // focused window on the current workspace. ++ if(!param) ++ break; ++ } ++ } ++ } ++ ++ // By default only non minimized windows are activated. ++ // This activates all windows in the current workspace. ++ _activateAllWindows() { ++ // First activate first window so workspace is switched if needed. ++ // We don't do this if isolation is on! ++ if (!this._dtdSettings.get_boolean('isolate-workspaces') && ++ !this._dtdSettings.get_boolean('isolate-monitors')) ++ this.app.activate(); ++ ++ // then activate all other app windows in the current workspace ++ let windows = this.getInterestingWindows(); ++ let activeWorkspace = global.workspace_manager.get_active_workspace_index(); ++ ++ if (windows.length <= 0) ++ return; ++ ++ let activatedWindows = 0; ++ ++ for (let i = windows.length - 1; i >= 0; i--) { ++ if (windows[i].get_workspace().index() == activeWorkspace) { ++ Main.activateWindow(windows[i]); ++ activatedWindows++; ++ } ++ } ++ } ++ ++ //This closes all windows of the app. ++ closeAllWindows() { ++ let windows = this.getInterestingWindows(); ++ for (let i = 0; i < windows.length; i++) ++ windows[i].delete(global.get_current_time()); ++ } ++ ++ _cycleThroughWindows(reversed) { ++ // Store for a little amount of time last clicked app and its windows ++ // since the order changes upon window interaction ++ let MEMORY_TIME=3000; ++ ++ let app_windows = this.getInterestingWindows(); ++ ++ if (app_windows.length <1) ++ return ++ ++ if (recentlyClickedAppLoopId > 0) ++ Mainloop.source_remove(recentlyClickedAppLoopId); ++ recentlyClickedAppLoopId = Mainloop.timeout_add(MEMORY_TIME, this._resetRecentlyClickedApp); ++ ++ // If there isn't already a list of windows for the current app, ++ // or the stored list is outdated, use the current windows list. ++ let monitorIsolation = this._dtdSettings.get_boolean('isolate-monitors'); ++ if (!recentlyClickedApp || ++ recentlyClickedApp.get_id() != this.app.get_id() || ++ recentlyClickedAppWindows.length != app_windows.length || ++ (recentlyClickedAppMonitor != this.monitorIndex && monitorIsolation)) { ++ recentlyClickedApp = this.app; ++ recentlyClickedAppWindows = app_windows; ++ recentlyClickedAppMonitor = this.monitorIndex; ++ recentlyClickedAppIndex = 0; ++ } ++ ++ if (reversed) { ++ recentlyClickedAppIndex--; ++ if (recentlyClickedAppIndex < 0) recentlyClickedAppIndex = recentlyClickedAppWindows.length - 1; ++ } else { ++ recentlyClickedAppIndex++; ++ } ++ let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length; ++ let window = recentlyClickedAppWindows[index]; ++ ++ Main.activateWindow(window); ++ } ++ ++ _resetRecentlyClickedApp() { ++ if (recentlyClickedAppLoopId > 0) ++ Mainloop.source_remove(recentlyClickedAppLoopId); ++ recentlyClickedAppLoopId=0; ++ recentlyClickedApp =null; ++ recentlyClickedAppWindows = null; ++ recentlyClickedAppIndex = 0; ++ recentlyClickedAppMonitor = -1; ++ ++ return false; ++ } ++ ++ // Filter out unnecessary windows, for instance ++ // nautilus desktop window. ++ getInterestingWindows() { ++ return getInterestingWindows(this.app, this._dtdSettings, this.monitorIndex); ++ } ++}; ++/** ++ * Extend AppIconMenu ++ * ++ * - Pass settings to the constructor ++ * - set popup arrow side based on dash orientation ++ * - Add close windows option based on quitfromdash extension ++ * (https://github.com/deuill/shell-extension-quitfromdash) ++ * - Add open windows thumbnails instead of list ++ * - update menu when application windows change ++ */ ++const MyAppIconMenu = class DashToDock_MyAppIconMenu extends AppDisplay.AppIconMenu { ++ ++ constructor(source, settings) { ++ let side = Utils.getPosition(settings); ++ ++ // Damm it, there has to be a proper way of doing this... ++ // As I can't call the parent parent constructor (?) passing the side ++ // parameter, I overwite what I need later ++ super(source); ++ ++ // Change the initialized side where required. ++ this._arrowSide = side; ++ this._boxPointer._arrowSide = side; ++ this._boxPointer._userArrowSide = side; ++ ++ this._dtdSettings = settings; ++ } ++ ++ _redisplay() { ++ this.removeAll(); ++ ++ if (this._dtdSettings.get_boolean('show-windows-preview')) { ++ // Display the app windows menu items and the separator between windows ++ // of the current desktop and other windows. ++ ++ this._allWindowsMenuItem = new PopupMenu.PopupSubMenuMenuItem(__('All Windows'), false); ++ this._allWindowsMenuItem.actor.hide(); ++ this.addMenuItem(this._allWindowsMenuItem); ++ ++ if (!this._source.app.is_window_backed()) { ++ this._appendSeparator(); ++ ++ let appInfo = this._source.app.get_app_info(); ++ let actions = appInfo.list_actions(); ++ if (this._source.app.can_open_new_window() && ++ actions.indexOf('new-window') == -1) { ++ this._newWindowMenuItem = this._appendMenuItem(_("New Window")); ++ this._newWindowMenuItem.connect('activate', () => { ++ if (this._source.app.state == Shell.AppState.STOPPED) ++ this._source.animateLaunch(); ++ ++ this._source.app.open_new_window(-1); ++ this.emit('activate-window', null); ++ }); ++ this._appendSeparator(); ++ } ++ ++ ++ if (AppDisplay.discreteGpuAvailable && ++ this._source.app.state == Shell.AppState.STOPPED && ++ actions.indexOf('activate-discrete-gpu') == -1) { ++ this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card")); ++ this._onDiscreteGpuMenuItem.connect('activate', () => { ++ if (this._source.app.state == Shell.AppState.STOPPED) ++ this._source.animateLaunch(); ++ ++ this._source.app.launch(0, -1, true); ++ this.emit('activate-window', null); ++ }); ++ } ++ ++ for (let i = 0; i < actions.length; i++) { ++ let action = actions[i]; ++ let item = this._appendMenuItem(appInfo.get_action_name(action)); ++ item.connect('activate', (emitter, event) => { ++ this._source.app.launch_action(action, event.get_time(), -1); ++ this.emit('activate-window', null); ++ }); ++ } ++ ++ let canFavorite = global.settings.is_writable('favorite-apps'); ++ ++ if (canFavorite) { ++ this._appendSeparator(); ++ ++ let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id()); ++ ++ if (isFavorite) { ++ let item = this._appendMenuItem(_("Remove from Favorites")); ++ item.connect('activate', () => { ++ let favs = AppFavorites.getAppFavorites(); ++ favs.removeFavorite(this._source.app.get_id()); ++ }); ++ } else { ++ let item = this._appendMenuItem(_("Add to Favorites")); ++ item.connect('activate', () => { ++ let favs = AppFavorites.getAppFavorites(); ++ favs.addFavorite(this._source.app.get_id()); ++ }); ++ } ++ } ++ ++ if (Shell.AppSystem.get_default().lookup_app('org.gnome.Software.desktop')) { ++ this._appendSeparator(); ++ let item = this._appendMenuItem(_("Show Details")); ++ item.connect('activate', () => { ++ let id = this._source.app.get_id(); ++ let args = GLib.Variant.new('(ss)', [id, '']); ++ Gio.DBus.get(Gio.BusType.SESSION, null, ++ function(o, res) { ++ let bus = Gio.DBus.get_finish(res); ++ bus.call('org.gnome.Software', ++ '/org/gnome/Software', ++ 'org.gtk.Actions', 'Activate', ++ GLib.Variant.new('(sava{sv})', ++ ['details', [args], null]), ++ null, 0, -1, null, null); ++ Main.overview.hide(); ++ }); ++ }); ++ } ++ } ++ ++ } else { ++ super._redisplay(); ++ } ++ ++ // quit menu ++ this._appendSeparator(); ++ this._quitfromDashMenuItem = this._appendMenuItem(_("Quit")); ++ this._quitfromDashMenuItem.connect('activate', () => { ++ this._source.closeAllWindows(); ++ }); ++ ++ this.update(); ++ } ++ ++ // update menu content when application windows change. This is desirable as actions ++ // acting on windows (closing) are performed while the menu is shown. ++ update() { ++ ++ if(this._dtdSettings.get_boolean('show-windows-preview')){ ++ ++ let windows = this._source.getInterestingWindows(); ++ ++ // update, show or hide the quit menu ++ if ( windows.length > 0) { ++ let quitFromDashMenuText = ""; ++ if (windows.length == 1) ++ this._quitfromDashMenuItem.label.set_text(_("Quit")); ++ else ++ this._quitfromDashMenuItem.label.set_text(_("Quit %d Windows").format(windows.length)); ++ ++ this._quitfromDashMenuItem.actor.show(); ++ ++ } else { ++ this._quitfromDashMenuItem.actor.hide(); ++ } ++ ++ // update, show, or hide the allWindows menu ++ // Check if there are new windows not already displayed. In such case, repopulate the allWindows ++ // menu. Windows removal is already handled by each preview being connected to the destroy signal ++ let old_windows = this._allWindowsMenuItem.menu._getMenuItems().map(function(item){ ++ return item._window; ++ }); ++ ++ let new_windows = windows.filter(function(w) {return old_windows.indexOf(w) < 0;}); ++ if (new_windows.length > 0) { ++ this._populateAllWindowMenu(windows); ++ ++ // Try to set the width to that of the submenu. ++ // TODO: can't get the actual size, getting a bit less. ++ // Temporary workaround: add 15px to compensate ++ this._allWindowsMenuItem.actor.width = this._allWindowsMenuItem.menu.actor.width + 15; ++ ++ } ++ ++ // The menu is created hidden and never hidded after being shown. Instead, a singlal ++ // connected to its items destroy will set is insensitive if no more windows preview are shown. ++ if (windows.length > 0){ ++ this._allWindowsMenuItem.actor.show(); ++ this._allWindowsMenuItem.setSensitive(true); ++ } ++ ++ // Update separators ++ this._getMenuItems().forEach(this._updateSeparatorVisibility.bind(this)); ++ } ++ ++ ++ } ++ ++ _populateAllWindowMenu(windows) { ++ ++ this._allWindowsMenuItem.menu.removeAll(); ++ ++ if (windows.length > 0) { ++ ++ let activeWorkspace = global.workspace_manager.get_active_workspace(); ++ let separatorShown = windows[0].get_workspace() != activeWorkspace; ++ ++ for (let i = 0; i < windows.length; i++) { ++ let window = windows[i]; ++ if (!separatorShown && window.get_workspace() != activeWorkspace) { ++ this._allWindowsMenuItem.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ separatorShown = true; ++ } ++ ++ let item = new WindowPreview.WindowPreviewMenuItem(window); ++ this._allWindowsMenuItem.menu.addMenuItem(item); ++ item.connect('activate', () => { ++ this.emit('activate-window', window); ++ }); ++ ++ // This is to achieve a more gracefull transition when the last windows is closed. ++ item.connect('destroy', () => { ++ if(this._allWindowsMenuItem.menu._getMenuItems().length == 1) // It's still counting the item just going to be destroyed ++ this._allWindowsMenuItem.setSensitive(false); ++ }); ++ } ++ } ++ } ++}; ++Signals.addSignalMethods(MyAppIconMenu.prototype); ++ ++// Filter out unnecessary windows, for instance ++// nautilus desktop window. ++function getInterestingWindows(app, settings, monitorIndex) { ++ let windows = app.get_windows().filter(function(w) { ++ return !w.skip_taskbar; ++ }); ++ ++ // When using workspace isolation, we filter out windows ++ // that are not in the current workspace ++ if (settings.get_boolean('isolate-workspaces')) ++ windows = windows.filter(function(w) { ++ return w.get_workspace().index() == global.workspace_manager.get_active_workspace_index(); ++ }); ++ ++ if (settings.get_boolean('isolate-monitors')) ++ windows = windows.filter(function(w) { ++ return w.get_monitor() == monitorIndex; ++ }); ++ ++ return windows; ++} ++ ++/** ++ * A wrapper class around the ShowAppsIcon class. ++ * ++ * - Pass settings to the constructor ++ * - set label position based on dash orientation (Note, I am reusing most machinery of the appIcon class) ++ * - implement a popupMenu based on the AppIcon code (Note, I am reusing most machinery of the appIcon class) ++ * ++ * I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973. ++ * thus use this pattern where the real showAppsIcon object is encaptulated, and a reference to it will be properly wired upon ++ * use of this class in place of the original showAppsButton. ++ * ++ */ ++ ++var ShowAppsIconWrapper = class DashToDock_ShowAppsIconWrapper { ++ constructor(settings) { ++ this._dtdSettings = settings; ++ this.realShowAppsIcon = new Dash.ShowAppsIcon(); ++ ++ /* the variable equivalent to toggleButton has a different name in the appIcon class ++ (actor): duplicate reference to easily reuse appIcon methods */ ++ this.actor = this.realShowAppsIcon.toggleButton; ++ ++ // Re-use appIcon methods ++ this._removeMenuTimeout = AppDisplay.AppIcon.prototype._removeMenuTimeout; ++ this._setPopupTimeout = AppDisplay.AppIcon.prototype._setPopupTimeout; ++ this._onButtonPress = AppDisplay.AppIcon.prototype._onButtonPress; ++ this._onKeyboardPopupMenu = AppDisplay.AppIcon.prototype._onKeyboardPopupMenu; ++ this._onLeaveEvent = AppDisplay.AppIcon.prototype._onLeaveEvent; ++ this._onTouchEvent = AppDisplay.AppIcon.prototype._onTouchEvent; ++ this._onMenuPoppedDown = AppDisplay.AppIcon.prototype._onMenuPoppedDown; ++ ++ // No action on clicked (showing of the appsview is controlled elsewhere) ++ this._onClicked = (actor, button) => { ++ this._removeMenuTimeout(); ++ }; ++ ++ this.actor.connect('leave-event', this._onLeaveEvent.bind(this)); ++ this.actor.connect('button-press-event', this._onButtonPress.bind(this)); ++ this.actor.connect('touch-event', this._onTouchEvent.bind(this)); ++ this.actor.connect('clicked', this._onClicked.bind(this)); ++ this.actor.connect('popup-menu', this._onKeyboardPopupMenu.bind(this)); ++ ++ this._menu = null; ++ this._menuManager = new PopupMenu.PopupMenuManager(this); ++ this._menuTimeoutId = 0; ++ ++ this.realShowAppsIcon._dtdSettings = settings; ++ this.realShowAppsIcon.showLabel = itemShowLabel; ++ } ++ ++ popupMenu() { ++ this._removeMenuTimeout(); ++ this.actor.fake_release(); ++ ++ if (!this._menu) { ++ this._menu = new MyShowAppsIconMenu(this, this._dtdSettings); ++ this._menu.connect('open-state-changed', (menu, isPoppedUp) => { ++ if (!isPoppedUp) ++ this._onMenuPoppedDown(); ++ }); ++ let id = Main.overview.connect('hiding', () => { ++ this._menu.close(); ++ }); ++ this._menu.actor.connect('destroy', function() { ++ Main.overview.disconnect(id); ++ }); ++ this._menuManager.addMenu(this._menu); ++ } ++ ++ //this.emit('menu-state-changed', true); ++ ++ this.actor.set_hover(true); ++ this._menu.popup(); ++ this._menuManager.ignoreRelease(); ++ this.emit('sync-tooltip'); ++ ++ return false; ++ } ++}; ++Signals.addSignalMethods(ShowAppsIconWrapper.prototype); ++ ++ ++/** ++ * A menu for the showAppsIcon ++ */ ++var MyShowAppsIconMenu = class DashToDock_MyShowAppsIconMenu extends MyAppIconMenu { ++ _redisplay() { ++ this.removeAll(); ++ ++ /* Translators: %s is "Settings", which is automatically translated. You ++ can also translate the full message if this fits better your language. */ ++ let name = __('Dash to Dock %s').format(_('Settings')) ++ let item = this._appendMenuItem(name); ++ ++ item.connect('activate', function () { ++ Util.spawn(["gnome-shell-extension-prefs", Me.metadata.uuid]); ++ }); ++ } ++}; ++ ++/** ++ * This function is used for both extendShowAppsIcon and extendDashItemContainer ++ */ ++function itemShowLabel() { ++ // Check if the label is still present at all. When switching workpaces, the ++ // item might have been destroyed in between. ++ if (!this._labelText || this.label.get_stage() == null) ++ return; ++ ++ this.label.set_text(this._labelText); ++ this.label.opacity = 0; ++ this.label.show(); ++ ++ let [stageX, stageY] = this.get_transformed_position(); ++ let node = this.label.get_theme_node(); ++ ++ let itemWidth = this.allocation.x2 - this.allocation.x1; ++ let itemHeight = this.allocation.y2 - this.allocation.y1; ++ ++ let labelWidth = this.label.get_width(); ++ let labelHeight = this.label.get_height(); ++ ++ let x, y, xOffset, yOffset; ++ ++ let position = Utils.getPosition(this._dtdSettings); ++ this._isHorizontal = ((position == St.Side.TOP) || (position == St.Side.BOTTOM)); ++ let labelOffset = node.get_length('-x-offset'); ++ ++ switch (position) { ++ case St.Side.LEFT: ++ yOffset = Math.floor((itemHeight - labelHeight) / 2); ++ y = stageY + yOffset; ++ xOffset = labelOffset; ++ x = stageX + this.get_width() + xOffset; ++ break; ++ case St.Side.RIGHT: ++ yOffset = Math.floor((itemHeight - labelHeight) / 2); ++ y = stageY + yOffset; ++ xOffset = labelOffset; ++ x = Math.round(stageX) - labelWidth - xOffset; ++ break; ++ case St.Side.TOP: ++ y = stageY + labelOffset + itemHeight; ++ xOffset = Math.floor((itemWidth - labelWidth) / 2); ++ x = stageX + xOffset; ++ break; ++ case St.Side.BOTTOM: ++ yOffset = labelOffset; ++ y = stageY - labelHeight - yOffset; ++ xOffset = Math.floor((itemWidth - labelWidth) / 2); ++ x = stageX + xOffset; ++ break; ++ } ++ ++ // keep the label inside the screen border ++ // Only needed fot the x coordinate. ++ ++ // Leave a few pixel gap ++ let gap = 5; ++ let monitor = Main.layoutManager.findMonitorForActor(this); ++ if (x - monitor.x < gap) ++ x += monitor.x - x + labelOffset; ++ else if (x + labelWidth > monitor.x + monitor.width - gap) ++ x -= x + labelWidth - (monitor.x + monitor.width) + gap; ++ ++ this.label.set_position(x, y); ++ Tweener.addTween(this.label, { ++ opacity: 255, ++ time: DASH_ITEM_LABEL_SHOW_TIME, ++ transition: 'easeOutQuad', ++ }); ++} +diff --git a/extensions/dash-to-dock/dash.js b/extensions/dash-to-dock/dash.js +new file mode 100644 +index 00000000..a646256b +--- /dev/null ++++ b/extensions/dash-to-dock/dash.js +@@ -0,0 +1,1171 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const Clutter = imports.gi.Clutter; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const GObject = imports.gi.GObject; ++const Gtk = imports.gi.Gtk; ++const Signals = imports.signals; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++ ++const AppDisplay = imports.ui.appDisplay; ++const AppFavorites = imports.ui.appFavorites; ++const Dash = imports.ui.dash; ++const DND = imports.ui.dnd; ++const IconGrid = imports.ui.iconGrid; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; ++const Util = imports.misc.util; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++const AppIcons = Me.imports.appIcons; ++ ++let DASH_ANIMATION_TIME = Dash.DASH_ANIMATION_TIME; ++let DASH_ITEM_LABEL_HIDE_TIME = Dash.DASH_ITEM_LABEL_HIDE_TIME; ++let DASH_ITEM_HOVER_TIMEOUT = Dash.DASH_ITEM_HOVER_TIMEOUT; ++ ++/** ++ * Extend DashItemContainer ++ * ++ * - Pass settings to the constructor ++ * - set label position based on dash orientation ++ * ++ * I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973. ++ * thus use this ugly pattern. ++ */ ++function extendDashItemContainer(dashItemContainer, settings) { ++ dashItemContainer._dtdSettings = settings; ++ dashItemContainer.showLabel = AppIcons.itemShowLabel; ++} ++ ++/** ++ * This class is a fork of the upstream DashActor class (ui.dash.js) ++ * ++ * Summary of changes: ++ * - passed settings to class as parameter ++ * - modified chldBox calculations for when 'show-apps-at-top' option is checked ++ * - handle horizontal dash ++ */ ++var MyDashActor = GObject.registerClass( ++class DashToDock_MyDashActor extends St.Widget { ++ ++ _init(settings) { ++ // a prefix is required to avoid conflicting with the parent class variable ++ this._dtdSettings = settings; ++ this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL); ++ ++ this._position = Utils.getPosition(settings); ++ this._isHorizontal = ((this._position == St.Side.TOP) || ++ (this._position == St.Side.BOTTOM)); ++ ++ let layout = new Clutter.BoxLayout({ ++ orientation: this._isHorizontal ? Clutter.Orientation.HORIZONTAL : Clutter.Orientation.VERTICAL ++ }); ++ ++ super._init({ ++ name: 'dash', ++ layout_manager: layout, ++ clip_to_allocation: true ++ }); ++ ++ // Since we are usually visible but not usually changing, make sure ++ // most repaint requests don't actually require us to repaint anything. ++ // This saves significant CPU when repainting the screen. ++ this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); ++ } ++ ++ vfunc_allocate(box, flags) { ++ this.set_allocation(box, flags); ++ let contentBox = box; ++ let availWidth = contentBox.x2 - contentBox.x1; ++ let availHeight = contentBox.y2 - contentBox.y1; ++ ++ let [appIcons, showAppsButton] = this.get_children(); ++ let [showAppsMinHeight, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth); ++ let [showAppsMinWidth, showAppsNatWidth] = showAppsButton.get_preferred_width(availHeight); ++ ++ let offset_x = this._isHorizontal?showAppsNatWidth:0; ++ let offset_y = this._isHorizontal?0:showAppsNatHeight; ++ ++ let childBox = new Clutter.ActorBox(); ++ if ((this._dtdSettings.get_boolean('show-apps-at-top') && !this._isHorizontal) ++ || (this._dtdSettings.get_boolean('show-apps-at-top') && !this._rtl) ++ || (!this._dtdSettings.get_boolean('show-apps-at-top') && this._isHorizontal && this._rtl)) { ++ childBox.x1 = contentBox.x1 + offset_x; ++ childBox.y1 = contentBox.y1 + offset_y; ++ childBox.x2 = contentBox.x2; ++ childBox.y2 = contentBox.y2; ++ appIcons.allocate(childBox, flags); ++ ++ childBox.y1 = contentBox.y1; ++ childBox.x1 = contentBox.x1; ++ childBox.x2 = contentBox.x1 + showAppsNatWidth; ++ childBox.y2 = contentBox.y1 + showAppsNatHeight; ++ showAppsButton.allocate(childBox, flags); ++ } ++ else { ++ childBox.x1 = contentBox.x1; ++ childBox.y1 = contentBox.y1; ++ childBox.x2 = contentBox.x2 - offset_x; ++ childBox.y2 = contentBox.y2 - offset_y; ++ appIcons.allocate(childBox, flags); ++ ++ childBox.x2 = contentBox.x2; ++ childBox.y2 = contentBox.y2; ++ childBox.x1 = contentBox.x2 - showAppsNatWidth; ++ childBox.y1 = contentBox.y2 - showAppsNatHeight; ++ showAppsButton.allocate(childBox, flags); ++ } ++ } ++ ++ vfunc_get_preferred_width(forHeight) { ++ // We want to request the natural height of all our children ++ // as our natural height, so we chain up to StWidget (which ++ // then calls BoxLayout), but we only request the showApps ++ // button as the minimum size ++ ++ let [, natWidth] = this.layout_manager.get_preferred_width(this, forHeight); ++ ++ let themeNode = this.get_theme_node(); ++ let [, showAppsButton] = this.get_children(); ++ let [minWidth, ] = showAppsButton.get_preferred_height(forHeight); ++ ++ return [minWidth, natWidth]; ++ } ++ ++ vfunc_get_preferred_height(forWidth) { ++ // We want to request the natural height of all our children ++ // as our natural height, so we chain up to StWidget (which ++ // then calls BoxLayout), but we only request the showApps ++ // button as the minimum size ++ ++ let [, natHeight] = this.layout_manager.get_preferred_height(this, forWidth); ++ ++ let themeNode = this.get_theme_node(); ++ let [, showAppsButton] = this.get_children(); ++ let [minHeight, ] = showAppsButton.get_preferred_height(forWidth); ++ ++ return [minHeight, natHeight]; ++ } ++}); ++ ++const baseIconSizes = [16, 22, 24, 32, 48, 64, 96, 128]; ++ ++/** ++ * This class is a fork of the upstream dash class (ui.dash.js) ++ * ++ * Summary of changes: ++ * - disconnect global signals adding a destroy method; ++ * - play animations even when not in overview mode ++ * - set a maximum icon size ++ * - show running and/or favorite applications ++ * - emit a custom signal when an app icon is added ++ * - hide showApps label when the custom menu is shown. ++ * - add scrollview ++ * ensure actor is visible on keyfocus inseid the scrollview ++ * - add 128px icon size, might be usefull for hidpi display ++ * - sync minimization application target position. ++ * - keep running apps ordered. ++ */ ++var MyDash = class DashToDock_MyDash { ++ ++ constructor(settings, remoteModel, monitorIndex) { ++ this._dtdSettings = settings; ++ ++ // Initialize icon variables and size ++ this._maxHeight = -1; ++ this.iconSize = this._dtdSettings.get_int('dash-max-icon-size'); ++ this._availableIconSizes = baseIconSizes; ++ this._shownInitially = false; ++ this._initializeIconSize(this.iconSize); ++ ++ this._remoteModel = remoteModel; ++ this._monitorIndex = monitorIndex; ++ this._position = Utils.getPosition(settings); ++ this._isHorizontal = ((this._position == St.Side.TOP) || ++ (this._position == St.Side.BOTTOM)); ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this._dragPlaceholder = null; ++ this._dragPlaceholderPos = -1; ++ this._animatingPlaceholdersCount = 0; ++ this._showLabelTimeoutId = 0; ++ this._resetHoverTimeoutId = 0; ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ this._labelShowing = false; ++ ++ this._container = new MyDashActor(settings); ++ this._scrollView = new St.ScrollView({ ++ name: 'dashtodockDashScrollview', ++ hscrollbar_policy: Gtk.PolicyType.NEVER, ++ vscrollbar_policy: Gtk.PolicyType.NEVER, ++ enable_mouse_scrolling: false ++ }); ++ ++ this._scrollView.connect('scroll-event', this._onScrollEvent.bind(this)); ++ ++ this._box = new St.BoxLayout({ ++ vertical: !this._isHorizontal, ++ clip_to_allocation: false, ++ x_align: Clutter.ActorAlign.START, ++ y_align: Clutter.ActorAlign.START ++ }); ++ this._box._delegate = this; ++ this._container.add_actor(this._scrollView); ++ this._scrollView.add_actor(this._box); ++ ++ // Create a wrapper around the real showAppsIcon in order to add a popupMenu. ++ let showAppsIconWrapper = new AppIcons.ShowAppsIconWrapper(this._dtdSettings); ++ showAppsIconWrapper.connect('menu-state-changed', (showAppsIconWrapper, opened) => { ++ this._itemMenuStateChanged(showAppsIconWrapper, opened); ++ }); ++ // an instance of the showAppsIcon class is encapsulated in the wrapper ++ this._showAppsIcon = showAppsIconWrapper.realShowAppsIcon; ++ ++ this._showAppsIcon.childScale = 1; ++ this._showAppsIcon.childOpacity = 255; ++ this._showAppsIcon.icon.setIconSize(this.iconSize); ++ this._hookUpLabel(this._showAppsIcon); ++ ++ this.showAppsButton = this._showAppsIcon.toggleButton; ++ ++ this._container.add_actor(this._showAppsIcon); ++ ++ let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; ++ this.actor = new St.Bin({ ++ child: this._container, ++ y_align: St.Align.START, ++ x_align: rtl ? St.Align.END : St.Align.START ++ }); ++ ++ if (this._isHorizontal) { ++ this.actor.connect('notify::width', () => { ++ if (this._maxHeight != this.actor.width) ++ this._queueRedisplay(); ++ this._maxHeight = this.actor.width; ++ }); ++ } ++ else { ++ this.actor.connect('notify::height', () => { ++ if (this._maxHeight != this.actor.height) ++ this._queueRedisplay(); ++ this._maxHeight = this.actor.height; ++ }); ++ } ++ ++ // Update minimization animation target position on allocation of the ++ // container and on scrollview change. ++ this._box.connect('notify::allocation', this._updateAppsIconGeometry.bind(this)); ++ let scrollViewAdjustment = this._isHorizontal ? this._scrollView.hscroll.adjustment : this._scrollView.vscroll.adjustment; ++ scrollViewAdjustment.connect('notify::value', this._updateAppsIconGeometry.bind(this)); ++ ++ this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); ++ ++ this._settings = new Gio.Settings({ ++ schema_id: 'org.gnome.shell' ++ }); ++ ++ this._appSystem = Shell.AppSystem.get_default(); ++ ++ this._signalsHandler.add([ ++ this._appSystem, ++ 'installed-changed', ++ () => { ++ AppFavorites.getAppFavorites().reload(); ++ this._queueRedisplay(); ++ } ++ ], [ ++ AppFavorites.getAppFavorites(), ++ 'changed', ++ this._queueRedisplay.bind(this) ++ ], [ ++ this._appSystem, ++ 'app-state-changed', ++ this._queueRedisplay.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-begin', ++ this._onDragBegin.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-end', ++ this._onDragEnd.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-cancelled', ++ this._onDragCancelled.bind(this) ++ ]); ++ } ++ ++ destroy() { ++ this._signalsHandler.destroy(); ++ } ++ ++ _onScrollEvent(actor, event) { ++ // If scroll is not used because the icon is resized, let the scroll event propagate. ++ if (!this._dtdSettings.get_boolean('icon-size-fixed')) ++ return Clutter.EVENT_PROPAGATE; ++ ++ // reset timeout to avid conflicts with the mousehover event ++ if (this._ensureAppIconVisibilityTimeoutId > 0) { ++ Mainloop.source_remove(this._ensureAppIconVisibilityTimeoutId); ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ } ++ ++ // Skip to avoid double events mouse ++ if (event.is_pointer_emulated()) ++ return Clutter.EVENT_STOP; ++ ++ let adjustment, delta; ++ ++ if (this._isHorizontal) ++ adjustment = this._scrollView.get_hscroll_bar().get_adjustment(); ++ else ++ adjustment = this._scrollView.get_vscroll_bar().get_adjustment(); ++ ++ let increment = adjustment.step_increment; ++ ++ switch (event.get_scroll_direction()) { ++ case Clutter.ScrollDirection.UP: ++ delta = -increment; ++ break; ++ case Clutter.ScrollDirection.DOWN: ++ delta = +increment; ++ break; ++ case Clutter.ScrollDirection.SMOOTH: ++ let [dx, dy] = event.get_scroll_delta(); ++ delta = dy * increment; ++ // Also consider horizontal component, for instance touchpad ++ if (this._isHorizontal) ++ delta += dx * increment; ++ break; ++ } ++ ++ adjustment.set_value(adjustment.get_value() + delta); ++ ++ return Clutter.EVENT_STOP; ++ } ++ ++ _onDragBegin() { ++ this._dragCancelled = false; ++ this._dragMonitor = { ++ dragMotion: this._onDragMotion.bind(this) ++ }; ++ DND.addDragMonitor(this._dragMonitor); ++ ++ if (this._box.get_n_children() == 0) { ++ this._emptyDropTarget = new Dash.EmptyDropTargetItem(); ++ this._box.insert_child_at_index(this._emptyDropTarget, 0); ++ this._emptyDropTarget.show(true); ++ } ++ } ++ ++ _onDragCancelled() { ++ this._dragCancelled = true; ++ this._endDrag(); ++ } ++ ++ _onDragEnd() { ++ if (this._dragCancelled) ++ return; ++ ++ this._endDrag(); ++ } ++ ++ _endDrag() { ++ this._clearDragPlaceholder(); ++ this._clearEmptyDropTarget(); ++ this._showAppsIcon.setDragApp(null); ++ DND.removeDragMonitor(this._dragMonitor); ++ } ++ ++ _onDragMotion(dragEvent) { ++ let app = Dash.getAppFromSource(dragEvent.source); ++ if (app == null) ++ return DND.DragMotionResult.CONTINUE; ++ ++ let showAppsHovered = this._showAppsIcon.contains(dragEvent.targetActor); ++ ++ if (!this._box.contains(dragEvent.targetActor) || showAppsHovered) ++ this._clearDragPlaceholder(); ++ ++ if (showAppsHovered) ++ this._showAppsIcon.setDragApp(app); ++ else ++ this._showAppsIcon.setDragApp(null); ++ ++ return DND.DragMotionResult.CONTINUE; ++ } ++ ++ _appIdListToHash(apps) { ++ let ids = {}; ++ for (let i = 0; i < apps.length; i++) ++ ids[apps[i].get_id()] = apps[i]; ++ return ids; ++ } ++ ++ _queueRedisplay() { ++ Main.queueDeferredWork(this._workId); ++ } ++ ++ _hookUpLabel(item, appIcon) { ++ item.child.connect('notify::hover', () => { ++ this._syncLabel(item, appIcon); ++ }); ++ ++ let id = Main.overview.connect('hiding', () => { ++ this._labelShowing = false; ++ item.hideLabel(); ++ }); ++ item.child.connect('destroy', function() { ++ Main.overview.disconnect(id); ++ }); ++ ++ if (appIcon) { ++ appIcon.connect('sync-tooltip', () => { ++ this._syncLabel(item, appIcon); ++ }); ++ } ++ } ++ ++ _createAppItem(app) { ++ let appIcon = new AppIcons.MyAppIcon(this._dtdSettings, this._remoteModel, app, this._monitorIndex, ++ { setSizeManually: true, ++ showLabel: false }); ++ ++ if (appIcon._draggable) { ++ appIcon._draggable.connect('drag-begin', () => { ++ appIcon.actor.opacity = 50; ++ }); ++ appIcon._draggable.connect('drag-end', () => { ++ appIcon.actor.opacity = 255; ++ }); ++ } ++ ++ appIcon.connect('menu-state-changed', (appIcon, opened) => { ++ this._itemMenuStateChanged(item, opened); ++ }); ++ ++ let item = new Dash.DashItemContainer(); ++ ++ extendDashItemContainer(item, this._dtdSettings); ++ item.setChild(appIcon.actor); ++ ++ appIcon.actor.connect('notify::hover', () => { ++ if (appIcon.actor.hover) { ++ this._ensureAppIconVisibilityTimeoutId = Mainloop.timeout_add(100, () => { ++ ensureActorVisibleInScrollView(this._scrollView, appIcon.actor); ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ } ++ else { ++ if (this._ensureAppIconVisibilityTimeoutId > 0) { ++ Mainloop.source_remove(this._ensureAppIconVisibilityTimeoutId); ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ } ++ } ++ }); ++ ++ appIcon.actor.connect('clicked', (actor) => { ++ ensureActorVisibleInScrollView(this._scrollView, actor); ++ }); ++ ++ appIcon.actor.connect('key-focus-in', (actor) => { ++ let [x_shift, y_shift] = ensureActorVisibleInScrollView(this._scrollView, actor); ++ ++ // This signal is triggered also by mouse click. The popup menu is opened at the original ++ // coordinates. Thus correct for the shift which is going to be applied to the scrollview. ++ if (appIcon._menu) { ++ appIcon._menu._boxPointer.xOffset = -x_shift; ++ appIcon._menu._boxPointer.yOffset = -y_shift; ++ } ++ }); ++ ++ // Override default AppIcon label_actor, now the ++ // accessible_name is set at DashItemContainer.setLabelText ++ appIcon.actor.label_actor = null; ++ item.setLabelText(app.get_name()); ++ ++ appIcon.icon.setIconSize(this.iconSize); ++ this._hookUpLabel(item, appIcon); ++ ++ return item; ++ } ++ ++ /** ++ * Return an array with the "proper" appIcons currently in the dash ++ */ ++ getAppIcons() { ++ // Only consider children which are "proper" ++ // icons (i.e. ignoring drag placeholders) and which are not ++ // animating out (which means they will be destroyed at the end of ++ // the animation) ++ let iconChildren = this._box.get_children().filter(function(actor) { ++ return actor.child && ++ actor.child._delegate && ++ actor.child._delegate.icon && ++ !actor.animatingOut; ++ }); ++ ++ let appIcons = iconChildren.map(function(actor) { ++ return actor.child._delegate; ++ }); ++ ++ return appIcons; ++ } ++ ++ _updateAppsIconGeometry() { ++ let appIcons = this.getAppIcons(); ++ appIcons.forEach(function(icon) { ++ icon.updateIconGeometry(); ++ }); ++ } ++ ++ _itemMenuStateChanged(item, opened) { ++ // When the menu closes, it calls sync_hover, which means ++ // that the notify::hover handler does everything we need to. ++ if (opened) { ++ if (this._showLabelTimeoutId > 0) { ++ Mainloop.source_remove(this._showLabelTimeoutId); ++ this._showLabelTimeoutId = 0; ++ } ++ ++ item.hideLabel(); ++ } ++ else { ++ // I want to listen from outside when a menu is closed. I used to ++ // add a custom signal to the appIcon, since gnome 3.8 the signal ++ // calling this callback was added upstream. ++ this.emit('menu-closed'); ++ } ++ } ++ ++ _syncLabel(item, appIcon) { ++ let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover(); ++ ++ if (shouldShow) { ++ if (this._showLabelTimeoutId == 0) { ++ let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT; ++ this._showLabelTimeoutId = Mainloop.timeout_add(timeout, () => { ++ this._labelShowing = true; ++ item.showLabel(); ++ this._showLabelTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel'); ++ if (this._resetHoverTimeoutId > 0) { ++ Mainloop.source_remove(this._resetHoverTimeoutId); ++ this._resetHoverTimeoutId = 0; ++ } ++ } ++ } ++ else { ++ if (this._showLabelTimeoutId > 0) ++ Mainloop.source_remove(this._showLabelTimeoutId); ++ this._showLabelTimeoutId = 0; ++ item.hideLabel(); ++ if (this._labelShowing) { ++ this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT, () => { ++ this._labelShowing = false; ++ this._resetHoverTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing'); ++ } ++ } ++ } ++ ++ _adjustIconSize() { ++ // For the icon size, we only consider children which are "proper" ++ // icons (i.e. ignoring drag placeholders) and which are not ++ // animating out (which means they will be destroyed at the end of ++ // the animation) ++ let iconChildren = this._box.get_children().filter(function(actor) { ++ return actor.child && ++ actor.child._delegate && ++ actor.child._delegate.icon && ++ !actor.animatingOut; ++ }); ++ ++ iconChildren.push(this._showAppsIcon); ++ ++ if (this._maxHeight == -1) ++ return; ++ ++ // Check if the container is present in the stage. This avoids critical ++ // errors when unlocking the screen ++ if (!this._container.get_stage()) ++ return; ++ ++ let themeNode = this._container.get_theme_node(); ++ let maxAllocation = new Clutter.ActorBox({ ++ x1: 0, ++ y1: 0, ++ x2: this._isHorizontal ? this._maxHeight : 42 /* whatever */, ++ y2: this._isHorizontal ? 42 : this._maxHeight ++ }); ++ let maxContent = themeNode.get_content_box(maxAllocation); ++ let availHeight; ++ if (this._isHorizontal) ++ availHeight = maxContent.x2 - maxContent.x1; ++ else ++ availHeight = maxContent.y2 - maxContent.y1; ++ let spacing = themeNode.get_length('spacing'); ++ ++ let firstButton = iconChildren[0].child; ++ let firstIcon = firstButton._delegate.icon; ++ ++ let minHeight, natHeight, minWidth, natWidth; ++ ++ // Enforce the current icon size during the size request ++ firstIcon.setIconSize(this.iconSize); ++ [minHeight, natHeight] = firstButton.get_preferred_height(-1); ++ [minWidth, natWidth] = firstButton.get_preferred_width(-1); ++ ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ let iconSizes = this._availableIconSizes.map(function(s) { ++ return s * scaleFactor; ++ }); ++ ++ // Subtract icon padding and box spacing from the available height ++ if (this._isHorizontal) ++ availHeight -= iconChildren.length * (natWidth - this.iconSize * scaleFactor) + ++ (iconChildren.length - 1) * spacing; ++ else ++ availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) + ++ (iconChildren.length - 1) * spacing; ++ ++ let availSize = availHeight / iconChildren.length; ++ ++ ++ let newIconSize = this._availableIconSizes[0]; ++ for (let i = 0; i < iconSizes.length; i++) { ++ if (iconSizes[i] < availSize) ++ newIconSize = this._availableIconSizes[i]; ++ } ++ ++ if (newIconSize == this.iconSize) ++ return; ++ ++ let oldIconSize = this.iconSize; ++ this.iconSize = newIconSize; ++ this.emit('icon-size-changed'); ++ ++ let scale = oldIconSize / newIconSize; ++ for (let i = 0; i < iconChildren.length; i++) { ++ let icon = iconChildren[i].child._delegate.icon; ++ ++ // Set the new size immediately, to keep the icons' sizes ++ // in sync with this.iconSize ++ icon.setIconSize(this.iconSize); ++ ++ // Don't animate the icon size change when the overview ++ // is transitioning, or when initially filling ++ // the dash ++ if (Main.overview.animationInProgress || ++ !this._shownInitially) ++ continue; ++ ++ let [targetWidth, targetHeight] = icon.icon.get_size(); ++ ++ // Scale the icon's texture to the previous size and ++ // tween to the new size ++ icon.icon.set_size(icon.icon.width * scale, ++ icon.icon.height * scale); ++ ++ Tweener.addTween(icon.icon, ++ { width: targetWidth, ++ height: targetHeight, ++ time: DASH_ANIMATION_TIME, ++ transition: 'easeOutQuad', ++ }); ++ } ++ } ++ ++ _redisplay() { ++ let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); ++ ++ let running = this._appSystem.get_running(); ++ if (this._dtdSettings.get_boolean('isolate-workspaces') || ++ this._dtdSettings.get_boolean('isolate-monitors')) { ++ // When using isolation, we filter out apps that have no windows in ++ // the current workspace ++ let settings = this._dtdSettings; ++ let monitorIndex = this._monitorIndex; ++ running = running.filter(function(_app) { ++ return AppIcons.getInterestingWindows(_app, settings, monitorIndex).length != 0; ++ }); ++ } ++ ++ let children = this._box.get_children().filter(function(actor) { ++ return actor.child && ++ actor.child._delegate && ++ actor.child._delegate.app; ++ }); ++ // Apps currently in the dash ++ let oldApps = children.map(function(actor) { ++ return actor.child._delegate.app; ++ }); ++ // Apps supposed to be in the dash ++ let newApps = []; ++ ++ if (this._dtdSettings.get_boolean('show-favorites')) { ++ for (let id in favorites) ++ newApps.push(favorites[id]); ++ } ++ ++ // We reorder the running apps so that they don't change position on the ++ // dash with every redisplay() call ++ if (this._dtdSettings.get_boolean('show-running')) { ++ // First: add the apps from the oldApps list that are still running ++ for (let i = 0; i < oldApps.length; i++) { ++ let index = running.indexOf(oldApps[i]); ++ if (index > -1) { ++ let app = running.splice(index, 1)[0]; ++ if (this._dtdSettings.get_boolean('show-favorites') && (app.get_id() in favorites)) ++ continue; ++ newApps.push(app); ++ } ++ } ++ // Second: add the new apps ++ for (let i = 0; i < running.length; i++) { ++ let app = running[i]; ++ if (this._dtdSettings.get_boolean('show-favorites') && (app.get_id() in favorites)) ++ continue; ++ newApps.push(app); ++ } ++ } ++ ++ // Figure out the actual changes to the list of items; we iterate ++ // over both the list of items currently in the dash and the list ++ // of items expected there, and collect additions and removals. ++ // Moves are both an addition and a removal, where the order of ++ // the operations depends on whether we encounter the position ++ // where the item has been added first or the one from where it ++ // was removed. ++ // There is an assumption that only one item is moved at a given ++ // time; when moving several items at once, everything will still ++ // end up at the right position, but there might be additional ++ // additions/removals (e.g. it might remove all the launchers ++ // and add them back in the new order even if a smaller set of ++ // additions and removals is possible). ++ // If above assumptions turns out to be a problem, we might need ++ // to use a more sophisticated algorithm, e.g. Longest Common ++ // Subsequence as used by diff. ++ ++ let addedItems = []; ++ let removedActors = []; ++ ++ let newIndex = 0; ++ let oldIndex = 0; ++ while ((newIndex < newApps.length) || (oldIndex < oldApps.length)) { ++ // No change at oldIndex/newIndex ++ if (oldApps[oldIndex] && oldApps[oldIndex] == newApps[newIndex]) { ++ oldIndex++; ++ newIndex++; ++ continue; ++ } ++ ++ // App removed at oldIndex ++ if (oldApps[oldIndex] && (newApps.indexOf(oldApps[oldIndex]) == -1)) { ++ removedActors.push(children[oldIndex]); ++ oldIndex++; ++ continue; ++ } ++ ++ // App added at newIndex ++ if (newApps[newIndex] && (oldApps.indexOf(newApps[newIndex]) == -1)) { ++ let newItem = this._createAppItem(newApps[newIndex]); ++ addedItems.push({ app: newApps[newIndex], ++ item: newItem, ++ pos: newIndex }); ++ newIndex++; ++ continue; ++ } ++ ++ // App moved ++ let insertHere = newApps[newIndex + 1] && (newApps[newIndex + 1] == oldApps[oldIndex]); ++ let alreadyRemoved = removedActors.reduce(function(result, actor) { ++ let removedApp = actor.child._delegate.app; ++ return result || removedApp == newApps[newIndex]; ++ }, false); ++ ++ if (insertHere || alreadyRemoved) { ++ let newItem = this._createAppItem(newApps[newIndex]); ++ addedItems.push({ ++ app: newApps[newIndex], ++ item: newItem, ++ pos: newIndex + removedActors.length ++ }); ++ newIndex++; ++ } ++ else { ++ removedActors.push(children[oldIndex]); ++ oldIndex++; ++ } ++ } ++ ++ for (let i = 0; i < addedItems.length; i++) ++ this._box.insert_child_at_index(addedItems[i].item, ++ addedItems[i].pos); ++ ++ for (let i = 0; i < removedActors.length; i++) { ++ let item = removedActors[i]; ++ ++ // Don't animate item removal when the overview is transitioning ++ if (!Main.overview.animationInProgress) ++ item.animateOutAndDestroy(); ++ else ++ item.destroy(); ++ } ++ ++ this._adjustIconSize(); ++ ++ for (let i = 0; i < addedItems.length; i++) ++ // Emit a custom signal notifying that a new item has been added ++ this.emit('item-added', addedItems[i]); ++ ++ // Skip animations on first run when adding the initial set ++ // of items, to avoid all items zooming in at once ++ ++ let animate = this._shownInitially && ++ !Main.overview.animationInProgress; ++ ++ if (!this._shownInitially) ++ this._shownInitially = true; ++ ++ for (let i = 0; i < addedItems.length; i++) ++ addedItems[i].item.show(animate); ++ ++ // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 ++ // Without it, StBoxLayout may use a stale size cache ++ this._box.queue_relayout(); ++ ++ // This is required for icon reordering when the scrollview is used. ++ this._updateAppsIconGeometry(); ++ ++ // This will update the size, and the corresponding number for each icon ++ this._updateNumberOverlay(); ++ } ++ ++ _updateNumberOverlay() { ++ let appIcons = this.getAppIcons(); ++ let counter = 1; ++ appIcons.forEach(function(icon) { ++ if (counter < 10){ ++ icon.setNumberOverlay(counter); ++ counter++; ++ } ++ else if (counter == 10) { ++ icon.setNumberOverlay(0); ++ counter++; ++ } ++ else { ++ // No overlay after 10 ++ icon.setNumberOverlay(-1); ++ } ++ icon.updateNumberOverlay(); ++ }); ++ ++ } ++ ++ toggleNumberOverlay(activate) { ++ let appIcons = this.getAppIcons(); ++ appIcons.forEach(function(icon) { ++ icon.toggleNumberOverlay(activate); ++ }); ++ } ++ ++ _initializeIconSize(max_size) { ++ let max_allowed = baseIconSizes[baseIconSizes.length-1]; ++ max_size = Math.min(max_size, max_allowed); ++ ++ if (this._dtdSettings.get_boolean('icon-size-fixed')) ++ this._availableIconSizes = [max_size]; ++ else { ++ this._availableIconSizes = baseIconSizes.filter(function(val) { ++ return (val { ++ this._animatingPlaceholdersCount--; ++ }); ++ this._dragPlaceholder = null; ++ } ++ this._dragPlaceholderPos = -1; ++ } ++ ++ _clearEmptyDropTarget() { ++ if (this._emptyDropTarget) { ++ this._emptyDropTarget.animateOutAndDestroy(); ++ this._emptyDropTarget = null; ++ } ++ } ++ ++ handleDragOver(source, actor, x, y, time) { ++ let app = Dash.getAppFromSource(source); ++ ++ // Don't allow favoriting of transient apps ++ if (app == null || app.is_window_backed()) ++ return DND.DragMotionResult.NO_DROP; ++ ++ if (!this._settings.is_writable('favorite-apps') || !this._dtdSettings.get_boolean('show-favorites')) ++ return DND.DragMotionResult.NO_DROP; ++ ++ let favorites = AppFavorites.getAppFavorites().getFavorites(); ++ let numFavorites = favorites.length; ++ ++ let favPos = favorites.indexOf(app); ++ ++ let children = this._box.get_children(); ++ let numChildren = children.length; ++ let boxHeight = 0; ++ for (let i = 0; i < numChildren; i++) ++ boxHeight += this._isHorizontal?children[i].width:children[i].height; ++ ++ // Keep the placeholder out of the index calculation; assuming that ++ // the remove target has the same size as "normal" items, we don't ++ // need to do the same adjustment there. ++ if (this._dragPlaceholder) { ++ boxHeight -= this._isHorizontal?this._dragPlaceholder.width:this._dragPlaceholder.height; ++ numChildren--; ++ } ++ ++ let pos; ++ if (!this._emptyDropTarget) { ++ pos = Math.floor((this._isHorizontal?x:y) * numChildren / boxHeight); ++ if (pos > numChildren) ++ pos = numChildren; ++ } ++ else ++ pos = 0; // always insert at the top when dash is empty ++ ++ // Take into account childredn position in rtl ++ if (this._isHorizontal && (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)) ++ pos = numChildren - pos; ++ ++ if ((pos != this._dragPlaceholderPos) && (pos <= numFavorites) && (this._animatingPlaceholdersCount == 0)) { ++ this._dragPlaceholderPos = pos; ++ ++ // Don't allow positioning before or after self ++ if ((favPos != -1) && (pos == favPos || pos == favPos + 1)) { ++ this._clearDragPlaceholder(); ++ return DND.DragMotionResult.CONTINUE; ++ } ++ ++ // If the placeholder already exists, we just move ++ // it, but if we are adding it, expand its size in ++ // an animation ++ let fadeIn; ++ if (this._dragPlaceholder) { ++ this._dragPlaceholder.destroy(); ++ fadeIn = false; ++ } ++ else ++ fadeIn = true; ++ ++ this._dragPlaceholder = new Dash.DragPlaceholderItem(); ++ this._dragPlaceholder.child.set_width (this.iconSize); ++ this._dragPlaceholder.child.set_height (this.iconSize / 2); ++ this._box.insert_child_at_index(this._dragPlaceholder, ++ this._dragPlaceholderPos); ++ this._dragPlaceholder.show(fadeIn); ++ // Ensure the next and previous icon are visible when moving the placeholder ++ // (I assume there's room for both of them) ++ if (this._dragPlaceholderPos > 1) ++ ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[this._dragPlaceholderPos-1]); ++ if (this._dragPlaceholderPos < this._box.get_children().length-1) ++ ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[this._dragPlaceholderPos+1]); ++ } ++ ++ // Remove the drag placeholder if we are not in the ++ // "favorites zone" ++ if (pos > numFavorites) ++ this._clearDragPlaceholder(); ++ ++ if (!this._dragPlaceholder) ++ return DND.DragMotionResult.NO_DROP; ++ ++ let srcIsFavorite = (favPos != -1); ++ ++ if (srcIsFavorite) ++ return DND.DragMotionResult.MOVE_DROP; ++ ++ return DND.DragMotionResult.COPY_DROP; ++ } ++ ++ /** ++ * Draggable target interface ++ */ ++ acceptDrop(source, actor, x, y, time) { ++ let app = Dash.getAppFromSource(source); ++ ++ // Don't allow favoriting of transient apps ++ if (app == null || app.is_window_backed()) ++ return false; ++ ++ if (!this._settings.is_writable('favorite-apps') || !this._dtdSettings.get_boolean('show-favorites')) ++ return false; ++ ++ let id = app.get_id(); ++ ++ let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); ++ ++ let srcIsFavorite = (id in favorites); ++ ++ let favPos = 0; ++ let children = this._box.get_children(); ++ for (let i = 0; i < this._dragPlaceholderPos; i++) { ++ if (this._dragPlaceholder && (children[i] == this._dragPlaceholder)) ++ continue; ++ ++ let childId = children[i].child._delegate.app.get_id(); ++ if (childId == id) ++ continue; ++ if (childId in favorites) ++ favPos++; ++ } ++ ++ // No drag placeholder means we don't wan't to favorite the app ++ // and we are dragging it to its original position ++ if (!this._dragPlaceholder) ++ return true; ++ ++ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ let appFavorites = AppFavorites.getAppFavorites(); ++ if (srcIsFavorite) ++ appFavorites.moveFavoriteToPos(id, favPos); ++ else ++ appFavorites.addFavoriteAtPos(id, favPos); ++ return false; ++ }); ++ ++ return true; ++ } ++ ++ showShowAppsButton() { ++ this.showAppsButton.visible = true ++ this.showAppsButton.set_width(-1) ++ this.showAppsButton.set_height(-1) ++ } ++ ++ hideShowAppsButton() { ++ this.showAppsButton.hide() ++ this.showAppsButton.set_width(0) ++ this.showAppsButton.set_height(0) ++ } ++}; ++ ++Signals.addSignalMethods(MyDash.prototype); ++ ++/** ++ * This is a copy of the same function in utils.js, but also adjust horizontal scrolling ++ * and perform few further cheks on the current value to avoid changing the values when ++ * it would be clamp to the current one in any case. ++ * Return the amount of shift applied ++ */ ++function ensureActorVisibleInScrollView(scrollView, actor) { ++ let adjust_v = true; ++ let adjust_h = true; ++ ++ let vadjustment = scrollView.vscroll.adjustment; ++ let hadjustment = scrollView.hscroll.adjustment; ++ let [vvalue, vlower, vupper, vstepIncrement, vpageIncrement, vpageSize] = vadjustment.get_values(); ++ let [hvalue, hlower, hupper, hstepIncrement, hpageIncrement, hpageSize] = hadjustment.get_values(); ++ ++ let [hvalue0, vvalue0] = [hvalue, vvalue]; ++ ++ let voffset = 0; ++ let hoffset = 0; ++ let fade = scrollView.get_effect('fade'); ++ if (fade) { ++ voffset = fade.vfade_offset; ++ hoffset = fade.hfade_offset; ++ } ++ ++ let box = actor.get_allocation_box(); ++ let y1 = box.y1, y2 = box.y2, x1 = box.x1, x2 = box.x2; ++ ++ let parent = actor.get_parent(); ++ while (parent != scrollView) { ++ if (!parent) ++ throw new Error('Actor not in scroll view'); ++ ++ let box = parent.get_allocation_box(); ++ y1 += box.y1; ++ y2 += box.y1; ++ x1 += box.x1; ++ x2 += box.x1; ++ parent = parent.get_parent(); ++ } ++ ++ if (y1 < vvalue + voffset) ++ vvalue = Math.max(0, y1 - voffset); ++ else if (vvalue < vupper - vpageSize && y2 > vvalue + vpageSize - voffset) ++ vvalue = Math.min(vupper -vpageSize, y2 + voffset - vpageSize); ++ ++ if (x1 < hvalue + hoffset) ++ hvalue = Math.max(0, x1 - hoffset); ++ else if (hvalue < hupper - hpageSize && x2 > hvalue + hpageSize - hoffset) ++ hvalue = Math.min(hupper - hpageSize, x2 + hoffset - hpageSize); ++ ++ if (vvalue !== vvalue0) { ++ Tweener.addTween(vadjustment, { value: vvalue, ++ time: Util.SCROLL_TIME, ++ transition: 'easeOutQuad' ++ }); ++ } ++ ++ if (hvalue !== hvalue0) { ++ Tweener.addTween(hadjustment, ++ { value: hvalue, ++ time: Util.SCROLL_TIME, ++ transition: 'easeOutQuad' }); ++ } ++ ++ return [hvalue- hvalue0, vvalue - vvalue0]; ++} +diff --git a/extensions/dash-to-dock/docking.js b/extensions/dash-to-dock/docking.js +new file mode 100644 +index 00000000..d35094b5 +--- /dev/null ++++ b/extensions/dash-to-dock/docking.js +@@ -0,0 +1,1853 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const Clutter = imports.gi.Clutter; ++const GLib = imports.gi.GLib; ++const GObject = imports.gi.GObject; ++const Gtk = imports.gi.Gtk; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++const Params = imports.misc.params; ++ ++const Main = imports.ui.main; ++const Dash = imports.ui.dash; ++const IconGrid = imports.ui.iconGrid; ++const Overview = imports.ui.overview; ++const OverviewControls = imports.ui.overviewControls; ++const PointerWatcher = imports.ui.pointerWatcher; ++const Tweener = imports.ui.tweener; ++const Signals = imports.signals; ++const ViewSelector = imports.ui.viewSelector; ++const WorkspaceSwitcherPopup= imports.ui.workspaceSwitcherPopup; ++const Layout = imports.ui.layout; ++const LayoutManager = imports.ui.main.layoutManager; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++const Intellihide = Me.imports.intellihide; ++const Theming = Me.imports.theming; ++const MyDash = Me.imports.dash; ++const LauncherAPI = Me.imports.launcherAPI; ++ ++const DOCK_DWELL_CHECK_INTERVAL = 100; ++ ++var State = { ++ HIDDEN: 0, ++ SHOWING: 1, ++ SHOWN: 2, ++ HIDING: 3 ++}; ++ ++const scrollAction = { ++ DO_NOTHING: 0, ++ CYCLE_WINDOWS: 1, ++ SWITCH_WORKSPACE: 2 ++}; ++ ++/** ++ * A simple St.Widget with one child whose allocation takes into account the ++ * slide out of its child via the _slidex parameter ([0:1]). ++ * ++ * Required since I want to track the input region of this container which is ++ * based on its allocation even if the child overlows the parent actor. By doing ++ * this the region of the dash that is slideout is not steling anymore the input ++ * regions making the extesion usable when the primary monitor is the right one. ++ * ++ * The slidex parameter can be used to directly animate the sliding. The parent ++ * must have a WEST (SOUTH) anchor_point to achieve the sliding to the RIGHT (BOTTOM) ++ * side. ++*/ ++var DashSlideContainer = GObject.registerClass( ++class DashToDock_DashSlideContainer extends St.Widget { ++ ++ _init(params) { ++ // Default local params ++ let localDefaults = { ++ side: St.Side.LEFT, ++ initialSlideValue: 1 ++ } ++ ++ let localParams = Params.parse(params, localDefaults, true); ++ ++ if (params) { ++ // Remove local params before passing the params to the parent ++ // constructor to avoid errors. ++ let prop; ++ for (prop in localDefaults) { ++ if ((prop in params)) ++ delete params[prop]; ++ } ++ } ++ ++ super._init(params); ++ this._child = null; ++ ++ // slide parameter: 1 = visible, 0 = hidden. ++ this._slidex = localParams.initialSlideValue; ++ this._side = localParams.side; ++ this._slideoutSize = 0; // minimum size when slided out ++ } ++ ++ vfunc_allocate(box, flags) { ++ this.set_allocation(box, flags); ++ ++ if (this._child == null) ++ return; ++ ++ let availWidth = box.x2 - box.x1; ++ let availHeight = box.y2 - box.y1; ++ let [, , natChildWidth, natChildHeight] = ++ this._child.get_preferred_size(); ++ ++ let childWidth = natChildWidth; ++ let childHeight = natChildHeight; ++ ++ let childBox = new Clutter.ActorBox(); ++ ++ let slideoutSize = this._slideoutSize; ++ ++ if (this._side == St.Side.LEFT) { ++ childBox.x1 = (this._slidex -1) * (childWidth - slideoutSize); ++ childBox.x2 = slideoutSize + this._slidex*(childWidth - slideoutSize); ++ childBox.y1 = 0; ++ childBox.y2 = childBox.y1 + childHeight; ++ } ++ else if ((this._side == St.Side.RIGHT) || (this._side == St.Side.BOTTOM)) { ++ childBox.x1 = 0; ++ childBox.x2 = childWidth; ++ childBox.y1 = 0; ++ childBox.y2 = childBox.y1 + childHeight; ++ } ++ else if (this._side == St.Side.TOP) { ++ childBox.x1 = 0; ++ childBox.x2 = childWidth; ++ childBox.y1 = (this._slidex -1) * (childHeight - slideoutSize); ++ childBox.y2 = slideoutSize + this._slidex * (childHeight - slideoutSize); ++ } ++ ++ this._child.allocate(childBox, flags); ++ this._child.set_clip(-childBox.x1, -childBox.y1, ++ -childBox.x1+availWidth, -childBox.y1 + availHeight); ++ } ++ ++ /** ++ * Just the child width but taking into account the slided out part ++ */ ++ vfunc_get_preferred_width(forHeight) { ++ let [minWidth, natWidth] = this._child.get_preferred_width(forHeight); ++ if ((this._side == St.Side.LEFT) || (this._side == St.Side.RIGHT)) { ++ minWidth = (minWidth - this._slideoutSize) * this._slidex + this._slideoutSize; ++ natWidth = (natWidth - this._slideoutSize) * this._slidex + this._slideoutSize; ++ } ++ return [minWidth, natWidth]; ++ } ++ ++ /** ++ * Just the child height but taking into account the slided out part ++ */ ++ vfunc_get_preferred_height(forWidth) { ++ let [minHeight, natHeight] = this._child.get_preferred_height(forWidth); ++ if ((this._side == St.Side.TOP) || (this._side == St.Side.BOTTOM)) { ++ minHeight = (minHeight - this._slideoutSize) * this._slidex + this._slideoutSize; ++ natHeight = (natHeight - this._slideoutSize) * this._slidex + this._slideoutSize; ++ } ++ return [minHeight, natHeight]; ++ } ++ ++ /** ++ * I was expecting it to be a virtual function... stil I don't understand ++ * how things work. ++ */ ++ add_child(actor) { ++ // I'm supposed to have only on child ++ if (this._child !== null) ++ this.remove_child(actor); ++ ++ this._child = actor; ++ super.add_child(actor); ++ } ++ ++ set slidex(value) { ++ this._slidex = value; ++ this._child.queue_relayout(); ++ } ++ ++ get slidex() { ++ return this._slidex; ++ } ++}); ++ ++var DockedDash = class DashToDock { ++ ++ constructor(settings, remoteModel, monitorIndex) { ++ this._rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL); ++ ++ // Load settings ++ this._settings = settings; ++ this._remoteModel = remoteModel; ++ this._monitorIndex = monitorIndex; ++ // Connect global signals ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this._bindSettingsChanges(); ++ ++ this._position = Utils.getPosition(settings); ++ this._isHorizontal = ((this._position == St.Side.TOP) || (this._position == St.Side.BOTTOM)); ++ ++ // Temporary ignore hover events linked to autohide for whatever reason ++ this._ignoreHover = false; ++ this._oldignoreHover = null; ++ // This variables are linked to the settings regardles of autohide or intellihide ++ // being temporary disable. Get set by _updateVisibilityMode; ++ this._autohideIsEnabled = null; ++ this._intellihideIsEnabled = null; ++ this._fixedIsEnabled = null; ++ ++ // Create intellihide object to monitor windows overlapping ++ this._intellihide = new Intellihide.Intellihide(this._settings, this._monitorIndex); ++ ++ // initialize dock state ++ this._dockState = State.HIDDEN; ++ ++ // Put dock on the required monitor ++ this._monitor = Main.layoutManager.monitors[this._monitorIndex]; ++ ++ // this store size and the position where the dash is shown; ++ // used by intellihide module to check window overlap. ++ this.staticBox = new Clutter.ActorBox(); ++ ++ // Initialize pressure barrier variables ++ this._canUsePressure = false; ++ this._pressureBarrier = null; ++ this._barrier = null; ++ this._removeBarrierTimeoutId = 0; ++ ++ // Initialize dwelling system variables ++ this._dockDwelling = false; ++ this._dockWatch = null; ++ this._dockDwellUserTime = 0; ++ this._dockDwellTimeoutId = 0 ++ ++ // Create a new dash object ++ this.dash = new MyDash.MyDash(this._settings, this._remoteModel, this._monitorIndex); ++ ++ if (!this._settings.get_boolean('show-show-apps-button')) ++ this.dash.hideShowAppsButton(); ++ ++ // Create the main actor and the containers for sliding in and out and ++ // centering, turn on track hover ++ ++ let positionStyleClass = ['top', 'right', 'bottom', 'left']; ++ // This is the centering actor ++ this.actor = new St.Bin({ ++ name: 'dashtodockContainer', ++ reactive: false, ++ style_class: positionStyleClass[this._position], ++ x_align: this._isHorizontal?St.Align.MIDDLE:St.Align.START, ++ y_align: this._isHorizontal?St.Align.START:St.Align.MIDDLE ++ }); ++ this.actor._delegate = this; ++ ++ // This is the sliding actor whose allocation is to be tracked for input regions ++ this._slider = new DashSlideContainer({ ++ side: this._position, ++ initialSlideValue: 0 ++ }); ++ ++ // This is the actor whose hover status us tracked for autohide ++ this._box = new St.BoxLayout({ ++ name: 'dashtodockBox', ++ reactive: true, ++ track_hover: true ++ }); ++ this._box.connect('notify::hover', this._hoverChanged.bind(this)); ++ ++ // Create and apply height constraint to the dash. It's controlled by this.actor height ++ this.constrainSize = new Clutter.BindConstraint({ ++ source: this.actor, ++ coordinate: this._isHorizontal?Clutter.BindCoordinate.WIDTH:Clutter.BindCoordinate.HEIGHT ++ }); ++ this.dash.actor.add_constraint(this.constrainSize); ++ ++ this._signalsHandler.add([ ++ Main.overview, ++ 'item-drag-begin', ++ this._onDragStart.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-end', ++ this._onDragEnd.bind(this) ++ ], [ ++ Main.overview, ++ 'item-drag-cancelled', ++ this._onDragEnd.bind(this) ++ ], [ ++ // update when workarea changes, for instance if other extensions modify the struts ++ //(like moving th panel at the bottom) ++ global.display, ++ 'workareas-changed', ++ this._resetPosition.bind(this) ++ ], [ ++ Main.overview, ++ 'showing', ++ this._onOverviewShowing.bind(this) ++ ], [ ++ Main.overview, ++ 'hiding', ++ this._onOverviewHiding.bind(this) ++ ], [ ++ // Hide on appview ++ Main.overview.viewSelector, ++ 'page-changed', ++ this._pageChanged.bind(this) ++ ], [ ++ Main.overview.viewSelector, ++ 'page-empty', ++ this._onPageEmpty.bind(this) ++ ], [ ++ // Ensure the ShowAppsButton status is kept in sync ++ Main.overview.viewSelector._showAppsButton, ++ 'notify::checked', ++ this._syncShowAppsButtonToggled.bind(this) ++ ], [ ++ global.display, ++ 'in-fullscreen-changed', ++ this._updateBarrier.bind(this) ++ ], [ ++ // Monitor windows overlapping ++ this._intellihide, ++ 'status-changed', ++ this._updateDashVisibility.bind(this) ++ ], [ ++ // Keep dragged icon consistent in size with this dash ++ this.dash, ++ 'icon-size-changed', ++ () => { Main.overview.dashIconSize = this.dash.iconSize; } ++ ], [ ++ // This duplicate the similar signal which is in owerview.js. ++ // Being connected and thus executed later this effectively ++ // overwrite any attempt to use the size of the default dash ++ //which given the customization is usually much smaller. ++ // I can't easily disconnect the original signal ++ Main.overview._controls.dash, ++ 'icon-size-changed', ++ () => { Main.overview.dashIconSize = this.dash.iconSize; } ++ ], [ ++ // sync hover after a popupmenu is closed ++ this.dash, ++ 'menu-closed', ++ () => { this._box.sync_hover() } ++ ]); ++ ++ this._injectionsHandler = new Utils.InjectionsHandler(); ++ this._themeManager = new Theming.ThemeManager(this._settings, this); ++ ++ // Since the actor is not a topLevel child and its parent is now not added to the Chrome, ++ // the allocation change of the parent container (slide in and slideout) doesn't trigger ++ // anymore an update of the input regions. Force the update manually. ++ this.actor.connect('notify::allocation', ++ Main.layoutManager._queueUpdateRegions.bind(Main.layoutManager)); ++ ++ this.dash._container.connect('allocation-changed', this._updateStaticBox.bind(this)); ++ this._slider.connect(this._isHorizontal ? 'notify::x' : 'notify::y', this._updateStaticBox.bind(this)); ++ ++ // Load optional features that need to be activated for one dock only ++ if (this._monitorIndex == this._settings.get_int('preferred-monitor')) ++ this._enableExtraFeatures(); ++ // Load optional features that need to be activated once per dock ++ this._optionalScrollWorkspaceSwitch(); ++ ++ // Delay operations that require the shell to be fully loaded and with ++ // user theme applied. ++ ++ this._paintId = this.actor.connect('paint', this._initialize.bind(this)); ++ ++ // Manage the which is used to reserve space in the overview for the dock ++ // Add and additional dashSpacer positioned according to the dash positioning. ++ // It gets restored on extension unload. ++ this._dashSpacer = new OverviewControls.DashSpacer(); ++ this._dashSpacer.setDashActor(this._box); ++ ++ if (this._position == St.Side.LEFT) ++ Main.overview._controls._group.insert_child_at_index(this._dashSpacer, this._rtl ? -1 : 0); // insert on first ++ else if (this._position == St.Side.RIGHT) ++ Main.overview._controls._group.insert_child_at_index(this._dashSpacer, this._rtl ? 0 : -1); // insert on last ++ else if (this._position == St.Side.TOP) ++ Main.overview._overview.insert_child_at_index(this._dashSpacer, 0); ++ else if (this._position == St.Side.BOTTOM) ++ Main.overview._overview.insert_child_at_index(this._dashSpacer, -1); ++ ++ // Add dash container actor and the container to the Chrome. ++ this.actor.set_child(this._slider); ++ this._slider.add_child(this._box); ++ this._box.add_actor(this.dash.actor); ++ ++ // Add aligning container without tracking it for input region ++ Main.uiGroup.add_child(this.actor); ++ ++ if (this._settings.get_boolean('dock-fixed')) { ++ // Note: tracking the fullscreen directly on the slider actor causes some hiccups when fullscreening ++ // windows of certain applications ++ Main.layoutManager._trackActor(this.actor, {affectsInputRegion: false, trackFullscreen: true}); ++ Main.layoutManager._trackActor(this._slider, {affectsStruts: true}); ++ } ++ else ++ Main.layoutManager._trackActor(this._slider); ++ ++ // Set initial position ++ this._resetDepth(); ++ this._resetPosition(); ++ } ++ ++ _initialize() { ++ if (this._paintId > 0) { ++ this.actor.disconnect(this._paintId); ++ this._paintId=0; ++ } ++ ++ // Apply custome css class according to the settings ++ this._themeManager.updateCustomTheme(); ++ ++ // Since Gnome 3.8 dragging an app without having opened the overview before cause the attemp to ++ //animate a null target since some variables are not initialized when the viewSelector is created ++ if (Main.overview.viewSelector._activePage == null) ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._workspacesPage; ++ ++ this._updateVisibilityMode(); ++ ++ // In case we are already inside the overview when the extension is loaded, ++ // for instance on unlocking the screen if it was locked with the overview open. ++ if (Main.overview.visibleTarget) { ++ this._onOverviewShowing(); ++ this._pageChanged(); ++ } ++ ++ // Setup pressure barrier (GS38+ only) ++ this._updatePressureBarrier(); ++ this._updateBarrier(); ++ ++ // setup dwelling system if pressure barriers are not available ++ this._setupDockDwellIfNeeded(); ++ } ++ ++ destroy() { ++ // Disconnect global signals ++ this._signalsHandler.destroy(); ++ // The dash, intellihide and themeManager have global signals as well internally ++ this.dash.destroy(); ++ this._intellihide.destroy(); ++ this._themeManager.destroy(); ++ ++ this._injectionsHandler.destroy(); ++ ++ // Destroy main clutter actor: this should be sufficient removing it and ++ // destroying all its children ++ this.actor.destroy(); ++ ++ // Remove barrier timeout ++ if (this._removeBarrierTimeoutId > 0) ++ Mainloop.source_remove(this._removeBarrierTimeoutId); ++ ++ // Remove existing barrier ++ this._removeBarrier(); ++ ++ // Remove pointer watcher ++ if (this._dockWatch) { ++ PointerWatcher.getPointerWatcher()._removeWatch(this._dockWatch); ++ this._dockWatch = null; ++ } ++ ++ // Remove the dashSpacer ++ this._dashSpacer.destroy(); ++ ++ } ++ ++ _bindSettingsChanges() { ++ this._signalsHandler.add([ ++ this._settings, ++ 'changed::scroll-action', ++ () => { this._optionalScrollWorkspaceSwitch(); } ++ ], [ ++ this._settings, ++ 'changed::dash-max-icon-size', ++ () => { this.dash.setIconSize(this._settings.get_int('dash-max-icon-size')); } ++ ], [ ++ this._settings, ++ 'changed::icon-size-fixed', ++ () => { this.dash.setIconSize(this._settings.get_int('dash-max-icon-size')); } ++ ], [ ++ this._settings, ++ 'changed::show-favorites', ++ () => { this.dash.resetAppIcons(); } ++ ], [ ++ this._settings, ++ 'changed::show-running', ++ () => { this.dash.resetAppIcons(); } ++ ], [ ++ this._settings, ++ 'changed::show-apps-at-top', ++ () => { this.dash.resetAppIcons(); } ++ ], [ ++ this._settings, ++ 'changed::show-show-apps-button', ++ () => { ++ if (this._settings.get_boolean('show-show-apps-button')) ++ this.dash.showShowAppsButton(); ++ else ++ this.dash.hideShowAppsButton(); ++ } ++ ], [ ++ this._settings, ++ 'changed::dock-fixed', ++ () => { ++ if (this._settings.get_boolean('dock-fixed')) { ++ Main.layoutManager._untrackActor(this.actor); ++ Main.layoutManager._trackActor(this.actor, {affectsInputRegion: false, trackFullscreen: true}); ++ Main.layoutManager._untrackActor(this._slider); ++ Main.layoutManager._trackActor(this._slider, {affectsStruts: true}); ++ } else { ++ Main.layoutManager._untrackActor(this.actor); ++ Main.layoutManager._untrackActor(this._slider); ++ Main.layoutManager._trackActor(this._slider); ++ } ++ ++ this._resetPosition(); ++ ++ // Add or remove barrier depending on if dock-fixed ++ this._updateBarrier(); ++ ++ this._updateVisibilityMode(); ++ } ++ ], [ ++ this._settings, ++ 'changed::intellihide', ++ this._updateVisibilityMode.bind(this) ++ ], [ ++ this._settings, ++ 'changed::intellihide-mode', ++ () => { this._intellihide.forceUpdate(); } ++ ], [ ++ this._settings, ++ 'changed::autohide', ++ () => { ++ this._updateVisibilityMode(); ++ this._updateBarrier(); ++ } ++ ], [ ++ this._settings, ++ 'changed::autohide-in-fullscreen', ++ this._updateBarrier.bind(this) ++ ], ++ [ ++ this._settings, ++ 'changed::extend-height', ++ this._resetPosition.bind(this) ++ ], [ ++ this._settings, ++ 'changed::height-fraction', ++ this._resetPosition.bind(this) ++ ], [ ++ this._settings, ++ 'changed::require-pressure-to-show', ++ () => { ++ // Remove pointer watcher ++ if (this._dockWatch) { ++ PointerWatcher.getPointerWatcher()._removeWatch(this._dockWatch); ++ this._dockWatch = null; ++ } ++ this._setupDockDwellIfNeeded(); ++ this._updateBarrier(); ++ } ++ ], [ ++ this._settings, ++ 'changed::pressure-threshold', ++ () => { ++ this._updatePressureBarrier(); ++ this._updateBarrier(); ++ } ++ ]); ++ ++ } ++ ++ /** ++ * This is call when visibility settings change ++ */ ++ _updateVisibilityMode() { ++ if (this._settings.get_boolean('dock-fixed')) { ++ this._fixedIsEnabled = true; ++ this._autohideIsEnabled = false; ++ this._intellihideIsEnabled = false; ++ } ++ else { ++ this._fixedIsEnabled = false; ++ this._autohideIsEnabled = this._settings.get_boolean('autohide') ++ this._intellihideIsEnabled = this._settings.get_boolean('intellihide') ++ } ++ ++ if (this._intellihideIsEnabled) ++ this._intellihide.enable(); ++ else ++ this._intellihide.disable(); ++ ++ this._updateDashVisibility(); ++ } ++ ++ /** ++ * Show/hide dash based on, in order of priority: ++ * overview visibility ++ * fixed mode ++ * intellihide ++ * autohide ++ * overview visibility ++ */ ++ _updateDashVisibility() { ++ if (Main.overview.visibleTarget) ++ return; ++ ++ if (this._fixedIsEnabled) { ++ this._removeAnimations(); ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ } ++ else if (this._intellihideIsEnabled) { ++ if (this._intellihide.getOverlapStatus()) { ++ this._ignoreHover = false; ++ // Do not hide if autohide is enabled and mouse is hover ++ if (!this._box.hover || !this._autohideIsEnabled) ++ this._animateOut(this._settings.get_double('animation-time'), 0); ++ } ++ else { ++ this._ignoreHover = true; ++ this._removeAnimations(); ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ } ++ } ++ else { ++ if (this._autohideIsEnabled) { ++ this._ignoreHover = false; ++ global.sync_pointer(); ++ ++ if (this._box.hover) ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ else ++ this._animateOut(this._settings.get_double('animation-time'), 0); ++ } ++ else ++ this._animateOut(this._settings.get_double('animation-time'), 0); ++ } ++ } ++ ++ _onOverviewShowing() { ++ this._ignoreHover = true; ++ this._intellihide.disable(); ++ this._removeAnimations(); ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ } ++ ++ _onOverviewHiding() { ++ this._ignoreHover = false; ++ this._intellihide.enable(); ++ this._updateDashVisibility(); ++ } ++ ++ _hoverChanged() { ++ if (!this._ignoreHover) { ++ // Skip if dock is not in autohide mode for instance because it is shown ++ // by intellihide. ++ if (this._autohideIsEnabled) { ++ if (this._box.hover) ++ this._show(); ++ else ++ this._hide(); ++ } ++ } ++ } ++ ++ getDockState() { ++ return this._dockState; ++ } ++ ++ _show() { ++ if ((this._dockState == State.HIDDEN) || (this._dockState == State.HIDING)) { ++ if (this._dockState == State.HIDING) ++ // suppress all potential queued hiding animations - i.e. added to Tweener but not started, ++ // always give priority to show ++ this._removeAnimations(); ++ ++ this.emit('showing'); ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ } ++ } ++ ++ _hide() { ++ // If no hiding animation is running or queued ++ if ((this._dockState == State.SHOWN) || (this._dockState == State.SHOWING)) { ++ let delay; ++ ++ if (this._dockState == State.SHOWING) ++ //if a show already started, let it finish; queue hide without removing the show. ++ // to obtain this I increase the delay to avoid the overlap and interference ++ // between the animations ++ delay = this._settings.get_double('hide-delay') + this._settings.get_double('animation-time'); ++ else ++ delay = this._settings.get_double('hide-delay'); ++ ++ this.emit('hiding'); ++ this._animateOut(this._settings.get_double('animation-time'), delay); ++ } ++ } ++ ++ _animateIn(time, delay) { ++ this._dockState = State.SHOWING; ++ ++ Tweener.addTween(this._slider, { ++ slidex: 1, ++ time: time, ++ delay: delay, ++ transition: 'easeOutQuad', ++ onComplete: () => { ++ this._dockState = State.SHOWN; ++ // Remove barrier so that mouse pointer is released and can access monitors on other side of dock ++ // NOTE: Delay needed to keep mouse from moving past dock and re-hiding dock immediately. This ++ // gives users an opportunity to hover over the dock ++ if (this._removeBarrierTimeoutId > 0) ++ Mainloop.source_remove(this._removeBarrierTimeoutId); ++ this._removeBarrierTimeoutId = Mainloop.timeout_add(100, this._removeBarrier.bind(this)); ++ } ++ }); ++ } ++ ++ _animateOut(time, delay) { ++ this._dockState = State.HIDING; ++ Tweener.addTween(this._slider, { ++ slidex: 0, ++ time: time, ++ delay: delay , ++ transition: 'easeOutQuad', ++ onComplete: () => { ++ this._dockState = State.HIDDEN; ++ // Remove queued barried removal if any ++ if (this._removeBarrierTimeoutId > 0) ++ Mainloop.source_remove(this._removeBarrierTimeoutId); ++ this._updateBarrier(); ++ } ++ }); ++ } ++ ++ /** ++ * Dwelling system based on the GNOME Shell 3.14 messageTray code. ++ */ ++ _setupDockDwellIfNeeded() { ++ // If we don't have extended barrier features, then we need ++ // to support the old tray dwelling mechanism. ++ if (!global.display.supports_extended_barriers() || !this._settings.get_boolean('require-pressure-to-show')) { ++ let pointerWatcher = PointerWatcher.getPointerWatcher(); ++ this._dockWatch = pointerWatcher.addWatch(DOCK_DWELL_CHECK_INTERVAL, this._checkDockDwell.bind(this)); ++ this._dockDwelling = false; ++ this._dockDwellUserTime = 0; ++ } ++ } ++ ++ _checkDockDwell(x, y) { ++ ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitor.index) ++ let shouldDwell; ++ // Check for the correct screen edge, extending the sensitive area to the whole workarea, ++ // minus 1 px to avoid conflicting with other active corners. ++ if (this._position == St.Side.LEFT) ++ shouldDwell = (x == this._monitor.x) && (y > workArea.y) && (y < workArea.y + workArea.height); ++ else if (this._position == St.Side.RIGHT) ++ shouldDwell = (x == this._monitor.x + this._monitor.width - 1) && (y > workArea.y) && (y < workArea.y + workArea.height); ++ else if (this._position == St.Side.TOP) ++ shouldDwell = (y == this._monitor.y) && (x > workArea.x) && (x < workArea.x + workArea.width); ++ else if (this._position == St.Side.BOTTOM) ++ shouldDwell = (y == this._monitor.y + this._monitor.height - 1) && (x > workArea.x) && (x < workArea.x + workArea.width); ++ ++ if (shouldDwell) { ++ // We only set up dwell timeout when the user is not hovering over the dock ++ // already (!this._box.hover). ++ // The _dockDwelling variable is used so that we only try to ++ // fire off one dock dwell - if it fails (because, say, the user has the mouse down), ++ // we don't try again until the user moves the mouse up and down again. ++ if (!this._dockDwelling && !this._box.hover && (this._dockDwellTimeoutId == 0)) { ++ // Save the interaction timestamp so we can detect user input ++ let focusWindow = global.display.focus_window; ++ this._dockDwellUserTime = focusWindow ? focusWindow.user_time : 0; ++ ++ this._dockDwellTimeoutId = Mainloop.timeout_add(this._settings.get_double('show-delay') * 1000, ++ this._dockDwellTimeout.bind(this)); ++ GLib.Source.set_name_by_id(this._dockDwellTimeoutId, '[dash-to-dock] this._dockDwellTimeout'); ++ } ++ this._dockDwelling = true; ++ } ++ else { ++ this._cancelDockDwell(); ++ this._dockDwelling = false; ++ } ++ } ++ ++ _cancelDockDwell() { ++ if (this._dockDwellTimeoutId != 0) { ++ Mainloop.source_remove(this._dockDwellTimeoutId); ++ this._dockDwellTimeoutId = 0; ++ } ++ } ++ ++ _dockDwellTimeout() { ++ this._dockDwellTimeoutId = 0; ++ ++ if (!this._settings.get_boolean('autohide-in-fullscreen') && this._monitor.inFullscreen) ++ return GLib.SOURCE_REMOVE; ++ ++ // We don't want to open the tray when a modal dialog ++ // is up, so we check the modal count for that. When we are in the ++ // overview we have to take the overview's modal push into account ++ if (Main.modalCount > (Main.overview.visible ? 1 : 0)) ++ return GLib.SOURCE_REMOVE; ++ ++ // If the user interacted with the focus window since we started the tray ++ // dwell (by clicking or typing), don't activate the message tray ++ let focusWindow = global.display.focus_window; ++ let currentUserTime = focusWindow ? focusWindow.user_time : 0; ++ if (currentUserTime != this._dockDwellUserTime) ++ return GLib.SOURCE_REMOVE; ++ ++ // Reuse the pressure version function, the logic is the same ++ this._onPressureSensed(); ++ return GLib.SOURCE_REMOVE; ++ } ++ ++ _updatePressureBarrier() { ++ this._canUsePressure = global.display.supports_extended_barriers(); ++ let pressureThreshold = this._settings.get_double('pressure-threshold'); ++ ++ // Remove existing pressure barrier ++ if (this._pressureBarrier) { ++ this._pressureBarrier.destroy(); ++ this._pressureBarrier = null; ++ } ++ ++ if (this._barrier) { ++ this._barrier.destroy(); ++ this._barrier = null; ++ } ++ ++ // Create new pressure barrier based on pressure threshold setting ++ if (this._canUsePressure) { ++ this._pressureBarrier = new Layout.PressureBarrier(pressureThreshold, this._settings.get_double('show-delay')*1000, ++ Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW); ++ this._pressureBarrier.connect('trigger', (barrier) => { ++ if (!this._settings.get_boolean('autohide-in-fullscreen') && this._monitor.inFullscreen) ++ return; ++ this._onPressureSensed(); ++ }); ++ } ++ } ++ ++ /** ++ * handler for mouse pressure sensed ++ */ ++ _onPressureSensed() { ++ if (Main.overview.visibleTarget) ++ return; ++ ++ // In case the mouse move away from the dock area before hovering it, in such case the leave event ++ // would never be triggered and the dock would stay visible forever. ++ let triggerTimeoutId = Mainloop.timeout_add(250, () => { ++ triggerTimeoutId = 0; ++ ++ let [x, y, mods] = global.get_pointer(); ++ let shouldHide = true; ++ switch (this._position) { ++ case St.Side.LEFT: ++ if (x <= this.staticBox.x2 && ++ x >= this._monitor.x && ++ y >= this._monitor.y && ++ y <= this._monitor.y + this._monitor.height) { ++ shouldHide = false; ++ } ++ break; ++ case St.Side.RIGHT: ++ if (x >= this.staticBox.x1 && ++ x <= this._monitor.x + this._monitor.width && ++ y >= this._monitor.y && ++ y <= this._monitor.y + this._monitor.height) { ++ shouldHide = false; ++ } ++ break; ++ case St.Side.TOP: ++ if (x >= this._monitor.x && ++ x <= this._monitor.x + this._monitor.width && ++ y <= this.staticBox.y2 && ++ y >= this._monitor.y) { ++ shouldHide = false; ++ } ++ break; ++ case St.Side.BOTTOM: ++ if (x >= this._monitor.x && ++ x <= this._monitor.x + this._monitor.width && ++ y >= this.staticBox.y1 && ++ y <= this._monitor.y + this._monitor.height) { ++ shouldHide = false; ++ } ++ } ++ if (shouldHide) { ++ this._hoverChanged(); ++ return GLib.SOURCE_REMOVE; ++ } ++ else { ++ return GLib.SOURCE_CONTINUE; ++ } ++ ++ }); ++ ++ this._show(); ++ } ++ ++ /** ++ * Remove pressure barrier ++ */ ++ _removeBarrier() { ++ if (this._barrier) { ++ if (this._pressureBarrier) ++ this._pressureBarrier.removeBarrier(this._barrier); ++ this._barrier.destroy(); ++ this._barrier = null; ++ } ++ this._removeBarrierTimeoutId = 0; ++ return false; ++ } ++ ++ /** ++ * Update pressure barrier size ++ */ ++ _updateBarrier() { ++ // Remove existing barrier ++ this._removeBarrier(); ++ ++ // The barrier needs to be removed in fullscreen with autohide disabled, otherwise the mouse can ++ // get trapped on monitor. ++ if (this._monitor.inFullscreen && !this._settings.get_boolean('autohide-in-fullscreen')) ++ return ++ ++ // Manually reset pressure barrier ++ // This is necessary because we remove the pressure barrier when it is triggered to show the dock ++ if (this._pressureBarrier) { ++ this._pressureBarrier._reset(); ++ this._pressureBarrier._isTriggered = false; ++ } ++ ++ // Create new barrier ++ // The barrier extends to the whole workarea, minus 1 px to avoid conflicting with other active corners ++ // Note: dash in fixed position doesn't use pressure barrier. ++ if (this._canUsePressure && this._autohideIsEnabled && this._settings.get_boolean('require-pressure-to-show')) { ++ let x1, x2, y1, y2, direction; ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitor.index) ++ ++ if (this._position == St.Side.LEFT) { ++ x1 = this._monitor.x + 1; ++ x2 = x1; ++ y1 = workArea.y + 1; ++ y2 = workArea.y + workArea.height - 1; ++ direction = Meta.BarrierDirection.POSITIVE_X; ++ } ++ else if (this._position == St.Side.RIGHT) { ++ x1 = this._monitor.x + this._monitor.width - 1; ++ x2 = x1; ++ y1 = workArea.y + 1; ++ y2 = workArea.y + workArea.height - 1; ++ direction = Meta.BarrierDirection.NEGATIVE_X; ++ } ++ else if (this._position == St.Side.TOP) { ++ x1 = workArea.x + 1; ++ x2 = workArea.x + workArea.width - 1; ++ y1 = this._monitor.y; ++ y2 = y1; ++ direction = Meta.BarrierDirection.POSITIVE_Y; ++ } ++ else if (this._position == St.Side.BOTTOM) { ++ x1 = workArea.x + 1; ++ x2 = workArea.x + workArea.width - 1; ++ y1 = this._monitor.y + this._monitor.height; ++ y2 = y1; ++ direction = Meta.BarrierDirection.NEGATIVE_Y; ++ } ++ ++ this._barrier = new Meta.Barrier({ ++ display: global.display, ++ x1: x1, ++ x2: x2, ++ y1: y1, ++ y2: y2, ++ directions: direction ++ }); ++ if (this._pressureBarrier) ++ this._pressureBarrier.addBarrier(this._barrier); ++ } ++ } ++ ++ _isPrimaryMonitor() { ++ return (this._monitorIndex == Main.layoutManager.primaryIndex); ++ } ++ ++ _resetPosition() { ++ // Ensure variables linked to settings are updated. ++ this._updateVisibilityMode(); ++ ++ let extendHeight = this._settings.get_boolean('extend-height'); ++ ++ // Note: do not use the workarea coordinates in the direction on which the dock is placed, ++ // to avoid a loop [position change -> workArea change -> position change] with ++ // fixed dock. ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitorIndex); ++ ++ // Reserve space for the dash on the overview ++ // if the dock is on the primary monitor ++ if (this._isPrimaryMonitor()) ++ this._dashSpacer.show(); ++ else ++ // No space is required in the overview of the dash ++ this._dashSpacer.hide(); ++ ++ let fraction = this._settings.get_double('height-fraction'); ++ ++ if (extendHeight) ++ fraction = 1; ++ else if ((fraction < 0) || (fraction > 1)) ++ fraction = 0.95; ++ ++ let anchor_point; ++ ++ if (this._isHorizontal) { ++ this.actor.width = Math.round( fraction * workArea.width); ++ ++ let pos_y; ++ if (this._position == St.Side.BOTTOM) { ++ pos_y = this._monitor.y + this._monitor.height; ++ anchor_point = Clutter.Gravity.SOUTH_WEST; ++ } ++ else { ++ pos_y = this._monitor.y; ++ anchor_point = Clutter.Gravity.NORTH_WEST; ++ } ++ ++ this.actor.move_anchor_point_from_gravity(anchor_point); ++ this.actor.x = workArea.x + Math.round((1 - fraction) / 2 * workArea.width); ++ this.actor.y = pos_y; ++ ++ if (extendHeight) { ++ this.dash._container.set_width(this.actor.width); ++ this.actor.add_style_class_name('extended'); ++ } ++ else { ++ this.dash._container.set_width(-1); ++ this.actor.remove_style_class_name('extended'); ++ } ++ } ++ else { ++ this.actor.height = Math.round(fraction * workArea.height); ++ ++ let pos_x; ++ if (this._position == St.Side.RIGHT) { ++ pos_x = this._monitor.x + this._monitor.width; ++ anchor_point = Clutter.Gravity.NORTH_EAST; ++ } ++ else { ++ pos_x = this._monitor.x; ++ anchor_point = Clutter.Gravity.NORTH_WEST; ++ } ++ ++ this.actor.move_anchor_point_from_gravity(anchor_point); ++ this.actor.x = pos_x; ++ this.actor.y = workArea.y + Math.round((1 - fraction) / 2 * workArea.height); ++ ++ if (extendHeight) { ++ this.dash._container.set_height(this.actor.height); ++ this.actor.add_style_class_name('extended'); ++ } ++ else { ++ this.dash._container.set_height(-1); ++ this.actor.remove_style_class_name('extended'); ++ } ++ } ++ ++ this._y0 = this.actor.y; ++ } ++ ++ // Set the dash at the correct depth in z ++ _resetDepth() { ++ // Keep the dash below the modalDialogGroup ++ Main.layoutManager.uiGroup.set_child_below_sibling(this.actor, Main.layoutManager.modalDialogGroup); ++ } ++ ++ _updateStaticBox() { ++ this.staticBox.init_rect( ++ this.actor.x + this._slider.x - (this._position == St.Side.RIGHT ? this._box.width : 0), ++ this.actor.y + this._slider.y - (this._position == St.Side.BOTTOM ? this._box.height : 0), ++ this._box.width, ++ this._box.height ++ ); ++ ++ this._intellihide.updateTargetBox(this.staticBox); ++ } ++ ++ _removeAnimations() { ++ Tweener.removeTweens(this._slider); ++ } ++ ++ _onDragStart() { ++ // The dash need to be above the top_window_group, otherwise it doesn't ++ // accept dnd of app icons when not in overiew mode. ++ Main.layoutManager.uiGroup.set_child_above_sibling(this.actor, global.top_window_group); ++ this._oldignoreHover = this._ignoreHover; ++ this._ignoreHover = true; ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ } ++ ++ _onDragEnd() { ++ // Restore drag default dash stack order ++ this._resetDepth(); ++ if (this._oldignoreHover !== null) ++ this._ignoreHover = this._oldignoreHover; ++ this._oldignoreHover = null; ++ this._box.sync_hover(); ++ if (Main.overview._shown) ++ this._pageChanged(); ++ } ++ ++ _pageChanged() { ++ let activePage = Main.overview.viewSelector.getActivePage(); ++ let dashVisible = (activePage == ViewSelector.ViewPage.WINDOWS || ++ activePage == ViewSelector.ViewPage.APPS); ++ ++ if (dashVisible) ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ else ++ this._animateOut(this._settings.get_double('animation-time'), 0); ++ } ++ ++ _onPageEmpty() { ++ /* The dash spacer is required only in the WINDOWS view if in the default position. ++ * The 'page-empty' signal is emitted in between a change of view, ++ * signalling the spacer can be added and removed without visible effect, ++ * as it's done for the upstream dashSpacer. ++ * ++ * Moreover, hiding the spacer ensure the appGrid allocaton is triggered. ++ * This matter as the appview spring animation is triggered by to first reallocaton of the appGrid, ++ * (See appDisplay.js, line 202 on GNOME Shell 3.14: ++ * this._grid.actor.connect('notify::allocation', ...) ++ * which in turn seems to be triggered by changes in the other actors in the overview. ++ * Normally, as far as I could understand, either the dashSpacer being hidden or the workspacesThumbnails ++ * sliding out would trigger the allocation. However, with no stock dash ++ * and no thumbnails, which happen if the user configured only 1 and static workspace, ++ * the animation out of icons is not played. ++ */ ++ ++ let activePage = Main.overview.viewSelector.getActivePage(); ++ this._dashSpacer.visible = (this._isHorizontal || activePage == ViewSelector.ViewPage.WINDOWS); ++ } ++ ++ /** ++ * Show dock and give key focus to it ++ */ ++ _onAccessibilityFocus() { ++ this._box.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); ++ this._animateIn(this._settings.get_double('animation-time'), 0); ++ } ++ ++ /** ++ * Keep ShowAppsButton status in sync with the overview status ++ */ ++ _syncShowAppsButtonToggled() { ++ let status = Main.overview.viewSelector._showAppsButton.checked; ++ if (this.dash.showAppsButton.checked !== status) ++ this.dash.showAppsButton.checked = status; ++ } ++ ++ // Optional features to be enabled only for the main Dock ++ _enableExtraFeatures() { ++ // Restore dash accessibility ++ Main.ctrlAltTabManager.addGroup( ++ this.dash.actor, _('Dash'), 'user-bookmarks-symbolic', ++ {focusCallback: this._onAccessibilityFocus.bind(this)}); ++ } ++ ++ /** ++ * Switch workspace by scrolling over the dock ++ */ ++ _optionalScrollWorkspaceSwitch() { ++ let label = 'optionalScrollWorkspaceSwitch'; ++ ++ function isEnabled() { ++ return this._settings.get_enum('scroll-action') === scrollAction.SWITCH_WORKSPACE; ++ } ++ ++ this._settings.connect('changed::scroll-action', () => { ++ if (isEnabled.bind(this)()) ++ enable.bind(this)(); ++ else ++ disable.bind(this)(); ++ }); ++ ++ if (isEnabled.bind(this)()) ++ enable.bind(this)(); ++ ++ function enable() { ++ this._signalsHandler.removeWithLabel(label); ++ ++ this._signalsHandler.addWithLabel(label, [ ++ this._box, ++ 'scroll-event', ++ onScrollEvent.bind(this) ++ ]); ++ ++ this._optionalScrollWorkspaceSwitchDeadTimeId = 0; ++ } ++ ++ function disable() { ++ this._signalsHandler.removeWithLabel(label); ++ ++ if (this._optionalScrollWorkspaceSwitchDeadTimeId > 0) { ++ Mainloop.source_remove(this._optionalScrollWorkspaceSwitchDeadTimeId); ++ this._optionalScrollWorkspaceSwitchDeadTimeId = 0; ++ } ++ } ++ ++ // This was inspired to desktop-scroller@obsidien.github.com ++ function onScrollEvent(actor, event) { ++ // When in overview change workscape only in windows view ++ if (Main.overview.visible && Main.overview.viewSelector.getActivePage() !== ViewSelector.ViewPage.WINDOWS) ++ return false; ++ ++ let activeWs = global.workspace_manager.get_active_workspace(); ++ let direction = null; ++ ++ switch (event.get_scroll_direction()) { ++ case Clutter.ScrollDirection.UP: ++ direction = Meta.MotionDirection.UP; ++ break; ++ case Clutter.ScrollDirection.DOWN: ++ direction = Meta.MotionDirection.DOWN; ++ break; ++ case Clutter.ScrollDirection.SMOOTH: ++ let [dx, dy] = event.get_scroll_delta(); ++ if (dy < 0) ++ direction = Meta.MotionDirection.UP; ++ else if (dy > 0) ++ direction = Meta.MotionDirection.DOWN; ++ break; ++ } ++ ++ if (direction !== null) { ++ // Prevent scroll events from triggering too many workspace switches ++ // by adding a 250ms deadtime between each scroll event. ++ // Usefull on laptops when using a touchpad. ++ ++ // During the deadtime do nothing ++ if (this._optionalScrollWorkspaceSwitchDeadTimeId > 0) ++ return false; ++ else ++ this._optionalScrollWorkspaceSwitchDeadTimeId = Mainloop.timeout_add(250, () => { ++ this._optionalScrollWorkspaceSwitchDeadTimeId = 0; ++ }); ++ ++ let ws; ++ ++ ws = activeWs.get_neighbor(direction) ++ ++ if (Main.wm._workspaceSwitcherPopup == null) ++ Main.wm._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup(); ++ // Set the actor non reactive, so that it doesn't prevent the ++ // clicks events from reaching the dash actor. I can't see a reason ++ // why it should be reactive. ++ Main.wm._workspaceSwitcherPopup.actor.reactive = false; ++ Main.wm._workspaceSwitcherPopup.connect('destroy', function() { ++ Main.wm._workspaceSwitcherPopup = null; ++ }); ++ ++ // Do not show wokspaceSwithcer in overview ++ if (!Main.overview.visible) ++ Main.wm._workspaceSwitcherPopup.display(direction, ws.index()); ++ Main.wm.actionMoveWorkspace(ws); ++ ++ return true; ++ } ++ else ++ return false; ++ } ++ } ++ ++ _activateApp(appIndex) { ++ let children = this.dash._box.get_children().filter(function(actor) { ++ return actor.child && ++ actor.child._delegate && ++ actor.child._delegate.app; ++ }); ++ ++ // Apps currently in the dash ++ let apps = children.map(function(actor) { ++ return actor.child._delegate; ++ }); ++ ++ // Activate with button = 1, i.e. same as left click ++ let button = 1; ++ if (appIndex < apps.length) ++ apps[appIndex].activate(button); ++ } ++}; ++ ++Signals.addSignalMethods(DockedDash.prototype); ++ ++/* ++ * Handle keybaord shortcuts ++ */ ++const DashToDock_KeyboardShortcuts_NUM_HOTKEYS = 10; ++ ++var KeyboardShortcuts = class DashToDock_KeyboardShortcuts { ++ ++ constructor(settings, allDocks){ ++ this._settings = settings; ++ this._allDocks = allDocks; ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this._hotKeysEnabled = false; ++ if (this._settings.get_boolean('hot-keys')) ++ this._enableHotKeys(); ++ ++ this._signalsHandler.add([ ++ this._settings, ++ 'changed::hot-keys', ++ () => { ++ if (this._settings.get_boolean('hot-keys')) ++ this._enableHotKeys.bind(this)(); ++ else ++ this._disableHotKeys.bind(this)(); ++ } ++ ]); ++ ++ this._optionalNumberOverlay(); ++ } ++ ++ destroy() { ++ // Remove keybindings ++ this._disableHotKeys(); ++ this._disableExtraShortcut(); ++ this._signalsHandler.destroy(); ++ } ++ ++ _enableHotKeys() { ++ if (this._hotKeysEnabled) ++ return; ++ ++ // Setup keyboard bindings for dash elements ++ let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-']; ++ keys.forEach( function(key) { ++ for (let i = 0; i < DashToDock_KeyboardShortcuts_NUM_HOTKEYS; i++) { ++ let appNum = i; ++ Main.wm.addKeybinding(key + (i + 1), this._settings, ++ Meta.KeyBindingFlags.NONE, ++ Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, ++ () => { ++ this._allDocks[0]._activateApp(appNum); ++ this._showOverlay(); ++ }); ++ } ++ }, this); ++ ++ this._hotKeysEnabled = true; ++ } ++ ++ _disableHotKeys() { ++ if (!this._hotKeysEnabled) ++ return; ++ ++ let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-']; ++ keys.forEach( function(key) { ++ for (let i = 0; i < DashToDock_KeyboardShortcuts_NUM_HOTKEYS; i++) ++ Main.wm.removeKeybinding(key + (i + 1)); ++ }, this); ++ ++ this._hotKeysEnabled = false; ++ } ++ ++ _optionalNumberOverlay() { ++ this._shortcutIsSet = false; ++ // Enable extra shortcut if either 'overlay' or 'show-dock' are true ++ if (this._settings.get_boolean('hot-keys') && ++ (this._settings.get_boolean('hotkeys-overlay') || this._settings.get_boolean('hotkeys-show-dock'))) ++ this._enableExtraShortcut(); ++ ++ this._signalsHandler.add([ ++ this._settings, ++ 'changed::hot-keys', ++ this._checkHotkeysOptions.bind(this) ++ ], [ ++ this._settings, ++ 'changed::hotkeys-overlay', ++ this._checkHotkeysOptions.bind(this) ++ ], [ ++ this._settings, ++ 'changed::hotkeys-show-dock', ++ this._checkHotkeysOptions.bind(this) ++ ]); ++ } ++ ++ _checkHotkeysOptions() { ++ if (this._settings.get_boolean('hot-keys') && ++ (this._settings.get_boolean('hotkeys-overlay') || this._settings.get_boolean('hotkeys-show-dock'))) ++ this._enableExtraShortcut(); ++ else ++ this._disableExtraShortcut(); ++ } ++ ++ _enableExtraShortcut() { ++ if (!this._shortcutIsSet) { ++ Main.wm.addKeybinding('shortcut', this._settings, ++ Meta.KeyBindingFlags.NONE, ++ Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, ++ this._showOverlay.bind(this)); ++ this._shortcutIsSet = true; ++ } ++ } ++ ++ _disableExtraShortcut() { ++ if (this._shortcutIsSet) { ++ Main.wm.removeKeybinding('shortcut'); ++ this._shortcutIsSet = false; ++ } ++ } ++ ++ _showOverlay() { ++ for (let i = 0; i < this._allDocks.length; i++) { ++ let dock = this._allDocks[i]; ++ if (dock._settings.get_boolean('hotkeys-overlay')) ++ dock.dash.toggleNumberOverlay(true); ++ ++ // Restart the counting if the shortcut is pressed again ++ if (dock._numberOverlayTimeoutId) { ++ Mainloop.source_remove(dock._numberOverlayTimeoutId); ++ dock._numberOverlayTimeoutId = 0; ++ } ++ ++ // Hide the overlay/dock after the timeout ++ let timeout = dock._settings.get_double('shortcut-timeout') * 1000; ++ dock._numberOverlayTimeoutId = Mainloop.timeout_add(timeout, () => { ++ dock._numberOverlayTimeoutId = 0; ++ dock.dash.toggleNumberOverlay(false); ++ // Hide the dock again if necessary ++ dock._updateDashVisibility(); ++ }); ++ ++ // Show the dock if it is hidden ++ if (dock._settings.get_boolean('hotkeys-show-dock')) { ++ let showDock = (dock._intellihideIsEnabled || dock._autohideIsEnabled); ++ if (showDock) ++ dock._show(); ++ } ++ } ++ } ++}; ++ ++/** ++ * Isolate overview to open new windows for inactive apps ++ * Note: the future implementaion is not fully contained here. Some bits are around in other methods of other classes. ++ * This class just take care of enabling/disabling the option. ++ */ ++var WorkspaceIsolation = class DashToDock_WorkspaceIsolation { ++ ++ constructor(settings, allDocks) { ++ ++ this._settings = settings; ++ this._allDocks = allDocks; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._injectionsHandler = new Utils.InjectionsHandler(); ++ ++ this._signalsHandler.add([ ++ this._settings, ++ 'changed::isolate-workspaces', ++ () => { ++ this._allDocks.forEach(function(dock) { ++ dock.dash.resetAppIcons(); ++ }); ++ if (this._settings.get_boolean('isolate-workspaces') || ++ this._settings.get_boolean('isolate-monitors')) ++ this._enable.bind(this)(); ++ else ++ this._disable.bind(this)(); ++ } ++ ],[ ++ this._settings, ++ 'changed::isolate-monitors', ++ () => { ++ this._allDocks.forEach(function(dock) { ++ dock.dash.resetAppIcons(); ++ }); ++ if (this._settings.get_boolean('isolate-workspaces') || ++ this._settings.get_boolean('isolate-monitors')) ++ this._enable.bind(this)(); ++ else ++ this._disable.bind(this)(); ++ } ++ ]); ++ ++ if (this._settings.get_boolean('isolate-workspaces') || ++ this._settings.get_boolean('isolate-monitors')) ++ this._enable(); ++ ++ } ++ ++ _enable() { ++ ++ // ensure I never double-register/inject ++ // although it should never happen ++ this._disable(); ++ ++ this._allDocks.forEach(function(dock) { ++ this._signalsHandler.addWithLabel('isolation', [ ++ global.display, ++ 'restacked', ++ dock.dash._queueRedisplay.bind(dock.dash) ++ ], [ ++ global.window_manager, ++ 'switch-workspace', ++ dock.dash._queueRedisplay.bind(dock.dash) ++ ]); ++ ++ // This last signal is only needed for monitor isolation, as windows ++ // might migrate from one monitor to another without triggering 'restacked' ++ if (this._settings.get_boolean('isolate-monitors')) ++ this._signalsHandler.addWithLabel('isolation', [ ++ global.display, ++ 'window-entered-monitor', ++ dock.dash._queueRedisplay.bind(dock.dash) ++ ]); ++ ++ }, this); ++ ++ // here this is the Shell.App ++ function IsolatedOverview() { ++ // These lines take care of Nautilus for icons on Desktop ++ let windows = this.get_windows().filter(function(w) { ++ return w.get_workspace().index() == global.workspace_manager.get_active_workspace_index(); ++ }); ++ if (windows.length == 1) ++ if (windows[0].skip_taskbar) ++ return this.open_new_window(-1); ++ ++ if (this.is_on_workspace(global.workspace_manager.get_active_workspace())) ++ return Main.activateWindow(windows[0]); ++ return this.open_new_window(-1); ++ } ++ ++ this._injectionsHandler.addWithLabel('isolation', [ ++ Shell.App.prototype, ++ 'activate', ++ IsolatedOverview ++ ]); ++ } ++ ++ _disable () { ++ this._signalsHandler.removeWithLabel('isolation'); ++ this._injectionsHandler.removeWithLabel('isolation'); ++ } ++ ++ destroy() { ++ this._signalsHandler.destroy(); ++ this._injectionsHandler.destroy(); ++ } ++}; ++ ++ ++var DockManager = class DashToDock_DockManager { ++ ++ constructor() { ++ this._remoteModel = new LauncherAPI.LauncherEntryRemoteModel(); ++ this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.dash-to-dock'); ++ this._oldDash = Main.overview._dash; ++ /* Array of all the docks created */ ++ this._allDocks = []; ++ this._createDocks(); ++ ++ // status variable: true when the overview is shown through the dash ++ // applications button. ++ this._forcedOverview = false; ++ ++ // Connect relevant signals to the toggling function ++ this._bindSettingsChanges(); ++ } ++ ++ _toggle() { ++ this._deleteDocks(); ++ this._createDocks(); ++ this.emit('toggled'); ++ } ++ ++ _bindSettingsChanges() { ++ // Connect relevant signals to the toggling function ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._signalsHandler.add([ ++ Meta.MonitorManager.get(), ++ 'monitors-changed', ++ this._toggle.bind(this) ++ ], [ ++ this._settings, ++ 'changed::multi-monitor', ++ this._toggle.bind(this) ++ ], [ ++ this._settings, ++ 'changed::preferred-monitor', ++ this._toggle.bind(this) ++ ], [ ++ this._settings, ++ 'changed::dock-position', ++ this._toggle.bind(this) ++ ], [ ++ this._settings, ++ 'changed::extend-height', ++ this._adjustPanelCorners.bind(this) ++ ], [ ++ this._settings, ++ 'changed::dock-fixed', ++ this._adjustPanelCorners.bind(this) ++ ]); ++ } ++ ++ _createDocks() { ++ ++ // If there are no monitors (headless configurations, but it can also happen temporary while disconnecting ++ // and reconnecting monitors), just do nothing. When a monitor will be connected we we'll be notified and ++ // and thus create the docks. This prevents pointing trying to access monitors throughout the code, were we ++ // are assuming that at least the primary monitor is present. ++ if (Main.layoutManager.monitors.length <= 0) { ++ return; ++ } ++ ++ this._preferredMonitorIndex = this._settings.get_int('preferred-monitor'); ++ // In case of multi-monitor, we consider the dock on the primary monitor to be the preferred (main) one ++ // regardless of the settings ++ // The dock goes on the primary monitor also if the settings are incosistent (e.g. desired monitor not connected). ++ if (this._settings.get_boolean('multi-monitor') || ++ this._preferredMonitorIndex < 0 || this._preferredMonitorIndex > Main.layoutManager.monitors.length - 1 ++ ) { ++ this._preferredMonitorIndex = Main.layoutManager.primaryIndex; ++ } else { ++ // Gdk and shell monitors numbering differ at least under wayland: ++ // While the primary monitor appears to be always index 0 in Gdk, ++ // the shell can assign a different number (Main.layoutManager.primaryMonitor) ++ // This ensure the indexing in the settings (Gdk) and in the shell are matched, ++ // i.e. that we start counting from the primaryMonitorIndex ++ this._preferredMonitorIndex = (Main.layoutManager.primaryIndex + this._preferredMonitorIndex) % Main.layoutManager.monitors.length ; ++ } ++ ++ // First we create the main Dock, to get the extra features to bind to this one ++ let dock = new DockedDash(this._settings, this._remoteModel, this._preferredMonitorIndex); ++ this._mainShowAppsButton = dock.dash.showAppsButton; ++ this._allDocks.push(dock); ++ ++ // connect app icon into the view selector ++ dock.dash.showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this)); ++ ++ // Make the necessary changes to Main.overview._dash ++ this._prepareMainDash(); ++ ++ // Adjust corners if necessary ++ this._adjustPanelCorners(); ++ ++ if (this._settings.get_boolean('multi-monitor')) { ++ let nMon = Main.layoutManager.monitors.length; ++ for (let iMon = 0; iMon < nMon; iMon++) { ++ if (iMon == this._preferredMonitorIndex) ++ continue; ++ let dock = new DockedDash(this._settings, this._remoteModel, iMon); ++ this._allDocks.push(dock); ++ // connect app icon into the view selector ++ dock.dash.showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this)); ++ } ++ } ++ ++ // Load optional features. We load *after* the docks are created, since ++ // we need to connect the signals to all dock instances. ++ this._workspaceIsolation = new WorkspaceIsolation(this._settings, this._allDocks); ++ this._keyboardShortcuts = new KeyboardShortcuts(this._settings, this._allDocks); ++ } ++ ++ _prepareMainDash() { ++ // Pretend I'm the dash: meant to make appgrd swarm animation come from the ++ // right position of the appShowButton. ++ Main.overview._dash = this._allDocks[0].dash; ++ ++ // set stored icon size to the new dash ++ Main.overview.dashIconSize = this._allDocks[0].dash.iconSize; ++ ++ // Hide usual Dash ++ Main.overview._controls.dash.actor.hide(); ++ ++ // Also set dash width to 1, so it's almost not taken into account by code ++ // calculaing the reserved space in the overview. The reason to keep it at 1 is ++ // to allow its visibility change to trigger an allocaion of the appGrid which ++ // in turn is triggergin the appsIcon spring animation, required when no other ++ // actors has this effect, i.e in horizontal mode and without the workspaceThumnails ++ // 1 static workspace only) ++ Main.overview._controls.dash.actor.set_width(1); ++ } ++ ++ _deleteDocks() { ++ // Remove extra features ++ this._workspaceIsolation.destroy(); ++ this._keyboardShortcuts.destroy(); ++ ++ // Delete all docks ++ let nDocks = this._allDocks.length; ++ for (let i = nDocks-1; i >= 0; i--) { ++ this._allDocks[i].destroy(); ++ this._allDocks.pop(); ++ } ++ } ++ ++ _restoreDash() { ++ Main.overview._controls.dash.actor.show(); ++ Main.overview._controls.dash.actor.set_width(-1); //reset default dash size ++ // This force the recalculation of the icon size ++ Main.overview._controls.dash._maxHeight = -1; ++ ++ // reset stored icon size to the default dash ++ Main.overview.dashIconSize = Main.overview._controls.dash.iconSize; ++ ++ Main.overview._dash = this._oldDash; ++ } ++ ++ _onShowAppsButtonToggled(button) { ++ // Sync the status of the default appButtons. Only if the two statuses are ++ // different, that means the user interacted with the extension provided ++ // application button, cutomize the behaviour. Otherwise the shell has changed the ++ // status (due to the _syncShowAppsButtonToggled function below) and it ++ // has already performed the desired action. ++ ++ let animate = this._settings.get_boolean('animate-show-apps'); ++ let selector = Main.overview.viewSelector; ++ ++ if (selector._showAppsButton.checked !== button.checked) { ++ // find visible view ++ let visibleView; ++ Main.overview.viewSelector.appDisplay._views.every(function(v, index) { ++ if (v.view.actor.visible) { ++ visibleView = index; ++ return false; ++ } ++ else ++ return true; ++ }); ++ ++ if (button.checked) { ++ // force spring animation triggering.By default the animation only ++ // runs if we are already inside the overview. ++ if (!Main.overview._shown) { ++ this._forcedOverview = true; ++ let view = Main.overview.viewSelector.appDisplay._views[visibleView].view; ++ let grid = view._grid; ++ if (animate) { ++ // Animate in the the appview, hide the appGrid to avoiud flashing ++ // Go to the appView before entering the overview, skipping the workspaces. ++ // Do this manually avoiding opacity in transitions so that the setting of the opacity ++ // to 0 doesn't get overwritten. ++ Main.overview.viewSelector._activePage.opacity = 0; ++ Main.overview.viewSelector._activePage.hide(); ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._appsPage; ++ Main.overview.viewSelector._activePage.show(); ++ grid.actor.opacity = 0; ++ ++ // The animation has to be trigered manually because the AppDisplay.animate ++ // method is waiting for an allocation not happening, as we skip the workspace view ++ // and the appgrid could already be allocated from previous shown. ++ // It has to be triggered after the overview is shown as wrong coordinates are obtained ++ // otherwise. ++ let overviewShownId = Main.overview.connect('shown', () => { ++ Main.overview.disconnect(overviewShownId); ++ Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ grid.actor.opacity = 255; ++ grid.animateSpring(IconGrid.AnimationDirection.IN, this._allDocks[0].dash.showAppsButton); ++ }); ++ }); ++ } ++ else { ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._appsPage; ++ Main.overview.viewSelector._activePage.show(); ++ grid.actor.opacity = 255; ++ } ++ ++ } ++ ++ // Finally show the overview ++ selector._showAppsButton.checked = true; ++ Main.overview.show(); ++ } ++ else { ++ if (this._forcedOverview) { ++ // force exiting overview if needed ++ ++ if (animate) { ++ // Manually trigger springout animation without activating the ++ // workspaceView to avoid the zoomout animation. Hide the appPage ++ // onComplete to avoid ugly flashing of original icons. ++ let view = Main.overview.viewSelector.appDisplay._views[visibleView].view; ++ let grid = view._grid; ++ view.animate(IconGrid.AnimationDirection.OUT, () => { ++ Main.overview.viewSelector._appsPage.hide(); ++ Main.overview.hide(); ++ selector._showAppsButton.checked = false; ++ this._forcedOverview = false; ++ }); ++ } ++ else { ++ Main.overview.hide(); ++ this._forcedOverview = false; ++ } ++ } ++ else { ++ selector._showAppsButton.checked = false; ++ this._forcedOverview = false; ++ } ++ } ++ } ++ ++ // whenever the button is unactivated even if not by the user still reset the ++ // forcedOverview flag ++ if (button.checked == false) ++ this._forcedOverview = false; ++ } ++ ++ destroy() { ++ this._signalsHandler.destroy(); ++ this._deleteDocks(); ++ this._revertPanelCorners(); ++ this._restoreDash(); ++ this._remoteModel.destroy(); ++ } ++ ++ /** ++ * Adjust Panel corners ++ */ ++ _adjustPanelCorners() { ++ let position = Utils.getPosition(this._settings); ++ let isHorizontal = ((position == St.Side.TOP) || (position == St.Side.BOTTOM)); ++ let extendHeight = this._settings.get_boolean('extend-height'); ++ let fixedIsEnabled = this._settings.get_boolean('dock-fixed'); ++ let dockOnPrimary = this._settings.get_boolean('multi-monitor') || ++ this._preferredMonitorIndex == Main.layoutManager.primaryIndex; ++ ++ if (!isHorizontal && dockOnPrimary && extendHeight && fixedIsEnabled) { ++ Main.panel._rightCorner.actor.hide(); ++ Main.panel._leftCorner.actor.hide(); ++ } ++ else ++ this._revertPanelCorners(); ++ } ++ ++ _revertPanelCorners() { ++ Main.panel._leftCorner.actor.show(); ++ Main.panel._rightCorner.actor.show(); ++ } ++}; ++Signals.addSignalMethods(DockManager.prototype); +diff --git a/extensions/dash-to-dock/extension.js b/extensions/dash-to-dock/extension.js +new file mode 100644 +index 00000000..f025fae8 +--- /dev/null ++++ b/extensions/dash-to-dock/extension.js +@@ -0,0 +1,23 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Docking = Me.imports.docking; ++ ++// We declare this with var so it can be accessed by other extensions in ++// GNOME Shell 3.26+ (mozjs52+). ++var dockManager; ++ ++function init() { ++ ExtensionUtils.initTranslations('dashtodock'); ++} ++ ++function enable() { ++ dockManager = new Docking.DockManager(); ++} ++ ++function disable() { ++ dockManager.destroy(); ++ ++ dockManager=null; ++} +diff --git a/extensions/dash-to-dock/intellihide.js b/extensions/dash-to-dock/intellihide.js +new file mode 100644 +index 00000000..f102ea33 +--- /dev/null ++++ b/extensions/dash-to-dock/intellihide.js +@@ -0,0 +1,321 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const GLib = imports.gi.GLib; ++const Mainloop = imports.mainloop; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++ ++const Main = imports.ui.main; ++const Signals = imports.signals; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++ ++// A good compromise between reactivity and efficiency; to be tuned. ++const INTELLIHIDE_CHECK_INTERVAL = 100; ++ ++const OverlapStatus = { ++ UNDEFINED: -1, ++ FALSE: 0, ++ TRUE: 1 ++}; ++ ++const IntellihideMode = { ++ ALL_WINDOWS: 0, ++ FOCUS_APPLICATION_WINDOWS: 1, ++ MAXIMIZED_WINDOWS : 2 ++}; ++ ++// List of windows type taken into account. Order is important (keep the original ++// enum order). ++const handledWindowTypes = [ ++ Meta.WindowType.NORMAL, ++ Meta.WindowType.DOCK, ++ Meta.WindowType.DIALOG, ++ Meta.WindowType.MODAL_DIALOG, ++ Meta.WindowType.TOOLBAR, ++ Meta.WindowType.MENU, ++ Meta.WindowType.UTILITY, ++ Meta.WindowType.SPLASHSCREEN ++]; ++ ++/** ++ * A rough and ugly implementation of the intellihide behaviour. ++ * Intallihide object: emit 'status-changed' signal when the overlap of windows ++ * with the provided targetBoxClutter.ActorBox changes; ++ */ ++var Intellihide = class DashToDock_Intellihide { ++ ++ constructor(settings, monitorIndex) { ++ // Load settings ++ this._settings = settings; ++ this._monitorIndex = monitorIndex; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._tracker = Shell.WindowTracker.get_default(); ++ this._focusApp = null; // The application whose window is focused. ++ this._topApp = null; // The application whose window is on top on the monitor with the dock. ++ ++ this._isEnabled = false; ++ this.status = OverlapStatus.UNDEFINED; ++ this._targetBox = null; ++ ++ this._checkOverlapTimeoutContinue = false; ++ this._checkOverlapTimeoutId = 0; ++ ++ this._trackedWindows = new Map(); ++ ++ // Connect global signals ++ this._signalsHandler.add([ ++ // Add signals on windows created from now on ++ global.display, ++ 'window-created', ++ this._windowCreated.bind(this) ++ ], [ ++ // triggered for instance when the window list order changes, ++ // included when the workspace is switched ++ global.display, ++ 'restacked', ++ this._checkOverlap.bind(this) ++ ], [ ++ // when windows are alwasy on top, the focus window can change ++ // without the windows being restacked. Thus monitor window focus change. ++ this._tracker, ++ 'notify::focus-app', ++ this._checkOverlap.bind(this) ++ ], [ ++ // update wne monitor changes, for instance in multimonitor when monitor are attached ++ Meta.MonitorManager.get(), ++ 'monitors-changed', ++ this._checkOverlap.bind(this) ++ ]); ++ } ++ ++ destroy() { ++ // Disconnect global signals ++ this._signalsHandler.destroy(); ++ ++ // Remove residual windows signals ++ this.disable(); ++ } ++ ++ enable() { ++ this._isEnabled = true; ++ this._status = OverlapStatus.UNDEFINED; ++ global.get_window_actors().forEach(function(wa) { ++ this._addWindowSignals(wa); ++ }, this); ++ this._doCheckOverlap(); ++ } ++ ++ disable() { ++ this._isEnabled = false; ++ ++ for (let wa of this._trackedWindows.keys()) { ++ this._removeWindowSignals(wa); ++ } ++ this._trackedWindows.clear(); ++ ++ if (this._checkOverlapTimeoutId > 0) { ++ Mainloop.source_remove(this._checkOverlapTimeoutId); ++ this._checkOverlapTimeoutId = 0; ++ } ++ } ++ ++ _windowCreated(display, metaWindow) { ++ this._addWindowSignals(metaWindow.get_compositor_private()); ++ } ++ ++ _addWindowSignals(wa) { ++ if (!this._handledWindow(wa)) ++ return; ++ let signalId = wa.connect('allocation-changed', this._checkOverlap.bind(this)); ++ this._trackedWindows.set(wa, signalId); ++ wa.connect('destroy', this._removeWindowSignals.bind(this)); ++ } ++ ++ _removeWindowSignals(wa) { ++ if (this._trackedWindows.get(wa)) { ++ wa.disconnect(this._trackedWindows.get(wa)); ++ this._trackedWindows.delete(wa); ++ } ++ ++ } ++ ++ updateTargetBox(box) { ++ this._targetBox = box; ++ this._checkOverlap(); ++ } ++ ++ forceUpdate() { ++ this._status = OverlapStatus.UNDEFINED; ++ this._doCheckOverlap(); ++ } ++ ++ getOverlapStatus() { ++ return (this._status == OverlapStatus.TRUE); ++ } ++ ++ _checkOverlap() { ++ if (!this._isEnabled || (this._targetBox == null)) ++ return; ++ ++ /* Limit the number of calls to the doCheckOverlap function */ ++ if (this._checkOverlapTimeoutId) { ++ this._checkOverlapTimeoutContinue = true; ++ return ++ } ++ ++ this._doCheckOverlap(); ++ ++ this._checkOverlapTimeoutId = Mainloop.timeout_add(INTELLIHIDE_CHECK_INTERVAL, () => { ++ this._doCheckOverlap(); ++ if (this._checkOverlapTimeoutContinue) { ++ this._checkOverlapTimeoutContinue = false; ++ return GLib.SOURCE_CONTINUE; ++ } else { ++ this._checkOverlapTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ } ++ }); ++ } ++ ++ _doCheckOverlap() { ++ ++ if (!this._isEnabled || (this._targetBox == null)) ++ return; ++ ++ let overlaps = OverlapStatus.FALSE; ++ let windows = global.get_window_actors(); ++ ++ if (windows.length > 0) { ++ /* ++ * Get the top window on the monitor where the dock is placed. ++ * The idea is that we dont want to overlap with the windows of the topmost application, ++ * event is it's not the focused app -- for instance because in multimonitor the user ++ * select a window in the secondary monitor. ++ */ ++ ++ let topWindow = null; ++ for (let i = windows.length - 1; i >= 0; i--) { ++ let meta_win = windows[i].get_meta_window(); ++ if (this._handledWindow(windows[i]) && (meta_win.get_monitor() == this._monitorIndex)) { ++ topWindow = meta_win; ++ break; ++ } ++ } ++ ++ if (topWindow !== null) { ++ this._topApp = this._tracker.get_window_app(topWindow); ++ // If there isn't a focused app, use that of the window on top ++ this._focusApp = this._tracker.focus_app || this._topApp ++ ++ windows = windows.filter(this._intellihideFilterInteresting, this); ++ ++ for (let i = 0; i < windows.length; i++) { ++ let win = windows[i].get_meta_window(); ++ ++ if (win) { ++ let rect = win.get_frame_rect(); ++ ++ let test = (rect.x < this._targetBox.x2) && ++ (rect.x + rect.width > this._targetBox.x1) && ++ (rect.y < this._targetBox.y2) && ++ (rect.y + rect.height > this._targetBox.y1); ++ ++ if (test) { ++ overlaps = OverlapStatus.TRUE; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ if (this._status !== overlaps) { ++ this._status = overlaps; ++ this.emit('status-changed', this._status); ++ } ++ ++ } ++ ++ // Filter interesting windows to be considered for intellihide. ++ // Consider all windows visible on the current workspace. ++ // Optionally skip windows of other applications ++ _intellihideFilterInteresting(wa) { ++ let meta_win = wa.get_meta_window(); ++ if (!this._handledWindow(wa)) ++ return false; ++ ++ let currentWorkspace = global.workspace_manager.get_active_workspace_index(); ++ let wksp = meta_win.get_workspace(); ++ let wksp_index = wksp.index(); ++ ++ // Depending on the intellihide mode, exclude non-relevent windows ++ switch (this._settings.get_enum('intellihide-mode')) { ++ case IntellihideMode.ALL_WINDOWS: ++ // Do nothing ++ break; ++ ++ case IntellihideMode.FOCUS_APPLICATION_WINDOWS: ++ // Skip windows of other apps ++ if (this._focusApp) { ++ // The DropDownTerminal extension is not an application per se ++ // so we match its window by wm class instead ++ if (meta_win.get_wm_class() == 'DropDownTerminalWindow') ++ return true; ++ ++ let currentApp = this._tracker.get_window_app(meta_win); ++ let focusWindow = global.display.get_focus_window() ++ ++ // Consider half maximized windows side by side ++ // and windows which are alwayson top ++ if((currentApp != this._focusApp) && (currentApp != this._topApp) ++ && !((focusWindow && focusWindow.maximized_vertically && !focusWindow.maximized_horizontally) ++ && (meta_win.maximized_vertically && !meta_win.maximized_horizontally) ++ && meta_win.get_monitor() == focusWindow.get_monitor()) ++ && !meta_win.is_above()) ++ return false; ++ } ++ break; ++ ++ case IntellihideMode.MAXIMIZED_WINDOWS: ++ // Skip unmaximized windows ++ if (!meta_win.maximized_vertically && !meta_win.maximized_horizontally) ++ return false; ++ break; ++ } ++ ++ if ( wksp_index == currentWorkspace && meta_win.showing_on_its_workspace() ) ++ return true; ++ else ++ return false; ++ ++ } ++ ++ // Filter windows by type ++ // inspired by Opacify@gnome-shell.localdomain.pl ++ _handledWindow(wa) { ++ let metaWindow = wa.get_meta_window(); ++ ++ if (!metaWindow) ++ return false; ++ ++ // The DropDownTerminal extension uses the POPUP_MENU window type hint ++ // so we match its window by wm class instead ++ if (metaWindow.get_wm_class() == 'DropDownTerminalWindow') ++ return true; ++ ++ let wtype = metaWindow.get_window_type(); ++ for (let i = 0; i < handledWindowTypes.length; i++) { ++ var hwtype = handledWindowTypes[i]; ++ if (hwtype == wtype) ++ return true; ++ else if (hwtype > wtype) ++ return false; ++ } ++ return false; ++ } ++}; ++ ++Signals.addSignalMethods(Intellihide.prototype); +diff --git a/extensions/dash-to-dock/launcherAPI.js b/extensions/dash-to-dock/launcherAPI.js +new file mode 100644 +index 00000000..f0b61990 +--- /dev/null ++++ b/extensions/dash-to-dock/launcherAPI.js +@@ -0,0 +1,239 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const Gio = imports.gi.Gio; ++const Signals = imports.signals; ++ ++var LauncherEntryRemoteModel = class DashToDock_LauncherEntryRemoteModel { ++ ++ constructor() { ++ this._entriesByDBusName = {}; ++ ++ this._launcher_entry_dbus_signal_id = ++ Gio.DBus.session.signal_subscribe(null, // sender ++ 'com.canonical.Unity.LauncherEntry', // iface ++ null, // member ++ null, // path ++ null, // arg0 ++ Gio.DBusSignalFlags.NONE, ++ this._onEntrySignalReceived.bind(this)); ++ ++ this._dbus_name_owner_changed_signal_id = ++ Gio.DBus.session.signal_subscribe('org.freedesktop.DBus', // sender ++ 'org.freedesktop.DBus', // interface ++ 'NameOwnerChanged', // member ++ '/org/freedesktop/DBus', // path ++ null, // arg0 ++ Gio.DBusSignalFlags.NONE, ++ this._onDBusNameOwnerChanged.bind(this)); ++ ++ this._acquireUnityDBus(); ++ } ++ ++ destroy() { ++ if (this._launcher_entry_dbus_signal_id) { ++ Gio.DBus.session.signal_unsubscribe(this._launcher_entry_dbus_signal_id); ++ } ++ ++ if (this._dbus_name_owner_changed_signal_id) { ++ Gio.DBus.session.signal_unsubscribe(this._dbus_name_owner_changed_signal_id); ++ } ++ ++ this._releaseUnityDBus(); ++ } ++ ++ size() { ++ return Object.keys(this._entriesByDBusName).length; ++ } ++ ++ lookupByDBusName(dbusName) { ++ return this._entriesByDBusName.hasOwnProperty(dbusName) ? this._entriesByDBusName[dbusName] : null; ++ } ++ ++ lookupById(appId) { ++ let ret = []; ++ for (let dbusName in this._entriesByDBusName) { ++ let entry = this._entriesByDBusName[dbusName]; ++ if (entry && entry.appId() == appId) { ++ ret.push(entry); ++ } ++ } ++ ++ return ret; ++ } ++ ++ addEntry(entry) { ++ let existingEntry = this.lookupByDBusName(entry.dbusName()); ++ if (existingEntry) { ++ existingEntry.update(entry); ++ } else { ++ this._entriesByDBusName[entry.dbusName()] = entry; ++ this.emit('entry-added', entry); ++ } ++ } ++ ++ removeEntry(entry) { ++ delete this._entriesByDBusName[entry.dbusName()] ++ this.emit('entry-removed', entry); ++ } ++ ++ _acquireUnityDBus() { ++ if (!this._unity_bus_id) { ++ Gio.DBus.session.own_name('com.canonical.Unity', ++ Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null); ++ } ++ } ++ ++ _releaseUnityDBus() { ++ if (this._unity_bus_id) { ++ Gio.DBus.session.unown_name(this._unity_bus_id); ++ this._unity_bus_id = 0; ++ } ++ } ++ ++ _onEntrySignalReceived(connection, sender_name, object_path, ++ interface_name, signal_name, parameters, user_data) { ++ if (!parameters || !signal_name) ++ return; ++ ++ if (signal_name == 'Update') { ++ if (!sender_name) { ++ return; ++ } ++ ++ this._handleUpdateRequest(sender_name, parameters); ++ } ++ } ++ ++ _onDBusNameOwnerChanged(connection, sender_name, object_path, ++ interface_name, signal_name, parameters, user_data) { ++ if (!parameters || !this.size()) ++ return; ++ ++ let [name, before, after] = parameters.deep_unpack(); ++ ++ if (!after) { ++ if (this._entriesByDBusName.hasOwnProperty(before)) { ++ this.removeEntry(this._entriesByDBusName[before]); ++ } ++ } ++ } ++ ++ _handleUpdateRequest(senderName, parameters) { ++ if (!senderName || !parameters) { ++ return; ++ } ++ ++ let [appUri, properties] = parameters.deep_unpack(); ++ let appId = appUri.replace(/(^\w+:|^)\/\//, ''); ++ let entry = this.lookupByDBusName(senderName); ++ ++ if (entry) { ++ entry.setDBusName(senderName); ++ entry.update(properties); ++ } else { ++ let entry = new LauncherEntryRemote(senderName, appId, properties); ++ this.addEntry(entry); ++ } ++ } ++}; ++Signals.addSignalMethods(LauncherEntryRemoteModel.prototype); ++ ++var LauncherEntryRemote = class DashToDock_LauncherEntryRemote { ++ ++ constructor(dbusName, appId, properties) { ++ this._dbusName = dbusName; ++ this._appId = appId; ++ this._count = 0; ++ this._countVisible = false; ++ this._progress = 0.0; ++ this._progressVisible = false; ++ this.update(properties); ++ } ++ ++ appId() { ++ return this._appId; ++ } ++ ++ dbusName() { ++ return this._dbusName; ++ } ++ ++ count() { ++ return this._count; ++ } ++ ++ setCount(count) { ++ if (this._count != count) { ++ this._count = count; ++ this.emit('count-changed', this._count); ++ } ++ } ++ ++ countVisible() { ++ return this._countVisible; ++ } ++ ++ setCountVisible(countVisible) { ++ if (this._countVisible != countVisible) { ++ this._countVisible = countVisible; ++ this.emit('count-visible-changed', this._countVisible); ++ } ++ } ++ ++ progress() { ++ return this._progress; ++ } ++ ++ setProgress(progress) { ++ if (this._progress != progress) { ++ this._progress = progress; ++ this.emit('progress-changed', this._progress); ++ } ++ } ++ ++ progressVisible() { ++ return this._progressVisible; ++ } ++ ++ setProgressVisible(progressVisible) { ++ if (this._progressVisible != progressVisible) { ++ this._progressVisible = progressVisible; ++ this.emit('progress-visible-changed', this._progressVisible); ++ } ++ } ++ ++ setDBusName(dbusName) { ++ if (this._dbusName != dbusName) { ++ let oldName = this._dbusName; ++ this._dbusName = dbusName; ++ this.emit('dbus-name-changed', oldName); ++ } ++ } ++ ++ update(other) { ++ if (other instanceof LauncherEntryRemote) { ++ this.setDBusName(other.dbusName()) ++ this.setCount(other.count()); ++ this.setCountVisible(other.countVisible()); ++ this.setProgress(other.progress()); ++ this.setProgressVisible(other.progressVisible()) ++ } else { ++ for (let property in other) { ++ if (other.hasOwnProperty(property)) { ++ if (property == 'count') { ++ this.setCount(other[property].get_int64()); ++ } else if (property == 'count-visible') { ++ this.setCountVisible(other[property].get_boolean()); ++ } if (property == 'progress') { ++ this.setProgress(other[property].get_double()); ++ } else if (property == 'progress-visible') { ++ this.setProgressVisible(other[property].get_boolean()); ++ } else { ++ // Not implemented yet ++ } ++ } ++ } ++ } ++ } ++}; ++Signals.addSignalMethods(LauncherEntryRemote.prototype); +diff --git a/extensions/dash-to-dock/media/glossy.svg b/extensions/dash-to-dock/media/glossy.svg +new file mode 100644 +index 00000000..55b71baa +--- /dev/null ++++ b/extensions/dash-to-dock/media/glossy.svg +@@ -0,0 +1,139 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-dock/media/highlight_stacked_bg.svg b/extensions/dash-to-dock/media/highlight_stacked_bg.svg +new file mode 100644 +index 00000000..19be5a9d +--- /dev/null ++++ b/extensions/dash-to-dock/media/highlight_stacked_bg.svg +@@ -0,0 +1,82 @@ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-dock/media/highlight_stacked_bg_h.svg b/extensions/dash-to-dock/media/highlight_stacked_bg_h.svg +new file mode 100644 +index 00000000..eeaa8691 +--- /dev/null ++++ b/extensions/dash-to-dock/media/highlight_stacked_bg_h.svg +@@ -0,0 +1,82 @@ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-dock/media/logo.svg b/extensions/dash-to-dock/media/logo.svg +new file mode 100644 +index 00000000..eebd0b1d +--- /dev/null ++++ b/extensions/dash-to-dock/media/logo.svg +@@ -0,0 +1,528 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Dash to Dock ++ Michele ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-dock/meson.build b/extensions/dash-to-dock/meson.build +new file mode 100644 +index 00000000..290374fb +--- /dev/null ++++ b/extensions/dash-to-dock/meson.build +@@ -0,0 +1,23 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_sources += files( ++ 'appIconIndicators.js', ++ 'appIcons.js', ++ 'dash.js', ++ 'docking.js', ++ 'extension.js', ++ 'intellihide.js', ++ 'launcherAPI.js', ++ 'prefs.js', ++ 'Settings.ui', ++ 'theming.js', ++ 'utils.js', ++ 'windowPreview.js' ++) ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') ++ ++install_data(['media/logo.svg', 'media/glossy.svg'], install_dir: join_paths(extensiondir, uuid, 'media')) +diff --git a/extensions/dash-to-dock/metadata.json.in b/extensions/dash-to-dock/metadata.json.in +new file mode 100644 +index 00000000..641a935c +--- /dev/null ++++ b/extensions/dash-to-dock/metadata.json.in +@@ -0,0 +1,12 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"original-author": "micxgx@gmail.com", ++"name": "Dash to Dock", ++"description": "A dock for the Gnome Shell. This extension moves the dash out of the overview transforming it in a dock for an easier launching of applications and a faster switching between windows and desktops. Side and bottom placement options are available.", ++"shell-version": [ "@shell_current@" ], ++"version": 66, ++"url": "https://micheleg.github.io/dash-to-dock/" ++} +diff --git a/extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml b/extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml +new file mode 100644 +index 00000000..9cf371ba +--- /dev/null ++++ b/extensions/dash-to-dock/org.gnome.shell.extensions.dash-to-dock.gschema.xml +@@ -0,0 +1,540 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 'LEFT' ++ Dock position ++ Dock is shown on the Left, Right, Top or Bottom side of the screen. ++ ++ ++ 0.2 ++ Animation time ++ Sets the time duration of the autohide effect. ++ ++ ++ 0.25 ++ Show delay ++ Sets the delay after the mouse reaches the screen border before showing the dock. ++ ++ ++ 0.20 ++ Show delay ++ Sets the delay after the mouse left the dock before hiding it. ++ ++ ++ false ++ Set a custom dash background background color ++ Sets the color for the dash background. ++ ++ ++ "#ffffff" ++ Dash background color. ++ Customize the background color of the dash. ++ ++ ++ 'DEFAULT' ++ Transparency mode for the dock ++ FIXED: constant transparency. DYNAMIC: dock takes the opaque style only when windows are close to it. ++ ++ ++ 'DEFAULT' ++ ... ++ DEFAULT: .... DOTS: .... ++ ++ ++ false ++ Use application icon dominant color for the indicator color ++ ++ ++ ++ false ++ Manually set the min and max opacity ++ For the dynamic mode, the min/max opacity values will be given by 'min-alpha' and 'max-alpha'. ++ ++ ++ 0.2 ++ Opacity of the dash background when free-floating ++ Sets the opacity of the dash background when no windows are close. ++ ++ ++ 0.8 ++ Opacity of the dash background when windows are close. ++ Sets the opacity of the dash background when windows are close. ++ ++ ++ 0.8 ++ Opacity of the dash background ++ Sets the opacity of the dash background when in autohide mode. ++ ++ ++ true ++ Dock dodges windows ++ Enable or disable intellihide mode ++ ++ ++ 'FOCUS_APPLICATION_WINDOWS' ++ Define which windows are considered for intellihide. ++ ++ ++ ++ true ++ Dock shown on mouse over ++ Enable or disable autohide mode ++ ++ ++ true ++ Require pressure to show dash ++ Enable or disable requiring pressure to show the dash ++ ++ ++ 100 ++ Pressure threshold ++ Sets how much pressure is needed to show the dash. ++ ++ ++ false ++ Enable autohide in fullscreen mode. ++ Enable autohide in fullscreen mode. ++ ++ ++ false ++ Dock always visible ++ Dock is always visible ++ ++ ++ true ++ Switch workspace by scrolling over the dock ++ Add the possibility to switch workspace by mouse scrolling over the dock. ++ ++ ++ 48 ++ Maximum dash icon size ++ Set the allowed maximum dash icon size. Allowed range: 16..64. ++ ++ ++ false ++ Fixed icon size ++ Keep the icon size fived by scrolling the dock. ++ ++ ++ false ++ Apply custom theme ++ Apply customization to the dash appearance ++ ++ ++ false ++ TODO ++ TODO ++ ++ ++ false ++ Customize the style of the running application indicators. ++ Customize the style of the running application indicators. ++ ++ ++ "#ffffff" ++ Running application indicators color ++ Customize the color of the running application indicators. ++ ++ ++ "#ffffff" ++ Running application indicators border color. ++ Customize the border color of the running application indicators. ++ ++ ++ 0 ++ Running application indicators border width. ++ Customize the border width of the running application indicators. ++ ++ ++ true ++ Show running apps ++ Show or hide running appplications icons in the dash ++ ++ ++ false ++ Provide workspace isolation ++ Dash shows only windows from the currentworkspace ++ ++ ++ false ++ Provide monitor isolation ++ Dash shows only windows from the monitor ++ ++ ++ true ++ Show preview of the open windows ++ Replace open windows list with windows previews ++ ++ ++ true ++ Show favorites apps ++ Show or hide favorite appplications icons in the dash ++ ++ ++ true ++ Show applications button ++ Show appplications button in the dash ++ ++ ++ false ++ Show application button at top ++ Show appplication button at top of the dash ++ ++ ++ true ++ Animate Show Applications from the desktop ++ Animate Show Applications from the desktop ++ ++ ++ true ++ Basic compatibility with bolt extensions ++ Make the extension work properly when bolt extensions is enabled ++ ++ ++ 0.90 ++ Dock max height (fraction of available space) ++ ++ ++ false ++ Extend the dock container to all the available height ++ ++ ++ -1 ++ Monitor on which putting the dock ++ Set on which monitor to put the dock, use -1 for the primary one ++ ++ ++ false ++ Enable multi-monitor docks ++ Show a dock on every monitor ++ ++ ++ true ++ Minimize on shift+click ++ ++ ++ true ++ Activate only one window ++ ++ ++ 'cycle-windows' ++ Action when clicking on a running app ++ Set the action that is executed when clicking on the icon of a running application ++ ++ ++ 'do-nothing' ++ Action when scrolling app ++ Set the action that is executed when scrolling on the application icon ++ ++ ++ 'minimize' ++ Action when shift+clicking on a running app ++ Set the action that is executed when shift+clicking on the icon of a running application ++ ++ ++ 'launch' ++ Action when clicking on a running app ++ Set the action that is executed when middle-clicking on the icon of a running application ++ ++ ++ 'launch' ++ Action when clicking on a running app ++ Set the action that is executed when shift+middle-clicking on the icon of a running application ++ ++ ++ true ++ Super Hot-Keys ++ Launch and switch between dash items using Super+(0-9) ++ ++ ++ true ++ Show the dock when using the hotkeys ++ The dock will be quickly shown so that the number-overlay is visible and app activation is easier ++ ++ ++ "<Super>q" ++ Keybinding to show the dock and the number overlay. ++ Behavior depends on hotkeys-show-dock and hotkeys-overlay. ++ ++ ++ q']]]> ++ Keybinding to show the dock and the number overlay. ++ Behavior depends on hotkeys-show-dock and hotkeys-overlay. ++ ++ ++ 2 ++ Timeout to hide the dock ++ Sets the time duration before the dock is hidden again. ++ ++ ++ true ++ Show the dock when using the hotkeys ++ The dock will be quickly shown so that the number-overlay is visible and app activation is easier ++ ++ ++ 1']]]> ++ Keybinding to launch 1st dash app ++ ++ Keybinding to launch 1st app. ++ ++ ++ ++ 2']]]> ++ Keybinding to launch 2nd dash app ++ ++ Keybinding to launch 2nd app. ++ ++ ++ ++ 3']]]> ++ Keybinding to launch 3rd dash app ++ ++ Keybinding to launch 3rd app. ++ ++ ++ ++ 4']]]> ++ Keybinding to launch 4th dash app ++ ++ Keybinding to launch 4th app. ++ ++ ++ ++ 5']]]> ++ Keybinding to launch 5th dash app ++ ++ Keybinding to launch 5th app. ++ ++ ++ ++ 6']]]> ++ Keybinding to launch 6th dash app ++ ++ Keybinding to launch 6th app. ++ ++ ++ ++ 7']]]> ++ Keybinding to launch 7th dash app ++ ++ Keybinding to launch 7th app. ++ ++ ++ ++ 8']]]> ++ Keybinding to launch 8th dash app ++ ++ Keybinding to launch 8th app. ++ ++ ++ ++ 9']]]> ++ Keybinding to launch 9th dash app ++ ++ Keybinding to launch 9th app. ++ ++ ++ ++ 0']]]> ++ Keybinding to launch 10th dash app ++ ++ Keybinding to launch 10th app. ++ ++ ++ ++ 1']]]> ++ Keybinding to trigger 1st dash app with shift behavior ++ ++ Keybinding to trigger 1st app with shift behavior. ++ ++ ++ ++ 2']]]> ++ Keybinding to trigger 2nd dash app with shift behavior ++ ++ Keybinding to trigger 2nd app with shift behavior. ++ ++ ++ ++ 3']]]> ++ Keybinding to trigger 3rd dash app with shift behavior ++ ++ Keybinding to trigger 3rd app with shift behavior. ++ ++ ++ ++ 4']]]> ++ Keybinding to trigger 4th dash app with shift behavior ++ ++ Keybinding to trigger 4th app with shift behavior. ++ ++ ++ ++ 5']]]> ++ Keybinding to trigger 5th dash app with shift behavior ++ ++ Keybinding to trigger 5th app with shift behavior. ++ ++ ++ ++ 6']]]> ++ Keybinding to trigger 6th dash app with shift behavior ++ ++ Keybinding to trigger 6th app with shift behavior. ++ ++ ++ ++ 7']]]> ++ Keybinding to trigger 7th dash app with shift behavior ++ ++ Keybinding to trigger 7th app with shift behavior. ++ ++ ++ ++ 8']]]> ++ Keybinding to trigger 8th dash app with shift behavior ++ ++ Keybinding to trigger 8th app with shift behavior. ++ ++ ++ ++ 9']]]> ++ Keybinding to trigger 9th dash app with shift behavior ++ ++ Keybinding to trigger 9th app with shift behavior. ++ ++ ++ ++ 0']]]> ++ Keybinding to trigger 10th dash app with shift behavior ++ ++ Keybinding to trigger 10th app with shift behavior. ++ ++ ++ ++ 1']]]> ++ Keybinding to trigger 1st dash app ++ ++ Keybinding to either show or launch the 1st application in the dash. ++ ++ ++ ++ 2']]]> ++ Keybinding to trigger 2nd dash app ++ ++ Keybinding to either show or launch the 2nd application in the dash. ++ ++ ++ ++ 3']]]> ++ Keybinding to trigger 3rd dash app ++ ++ Keybinding to either show or launch the 3rd application in the dash. ++ ++ ++ ++ 4']]]> ++ Keybinding to trigger 4th dash app ++ ++ Keybinding to either show or launch the 4th application in the dash. ++ ++ ++ ++ 5']]]> ++ Keybinding to trigger 5th dash app ++ ++ Keybinding to either show or launch the 5th application in the dash. ++ ++ ++ ++ 6']]]> ++ Keybinding to trigger 6th dash app ++ ++ Keybinding to either show or launch the 6th application in the dash. ++ ++ ++ ++ 7']]]> ++ Keybinding to trigger 7th dash app ++ ++ Keybinding to either show or launch the 7th application in the dash. ++ ++ ++ ++ 8']]]> ++ Keybinding to trigger 8th dash app ++ ++ Keybinding to either show or launch the 8th application in the dash. ++ ++ ++ ++ 9']]]> ++ Keybinding to trigger 9th dash app ++ ++ Keybinding to either show or launch the 9th application in the dash. ++ ++ ++ ++ 0']]]> ++ Keybinding to trigger 10th dash app ++ ++ Keybinding to either show or launch the 10th application in the dash. ++ ++ ++ ++ false ++ Force straight corners in dash ++ Make the borders in the dash non rounded ++ ++ ++ false ++ Enable unity7 like glossy backlit items ++ Emulate the unity7 backlit glossy items behaviour ++ ++ ++ +diff --git a/extensions/dash-to-dock/prefs.js b/extensions/dash-to-dock/prefs.js +new file mode 100644 +index 00000000..a72b1398 +--- /dev/null ++++ b/extensions/dash-to-dock/prefs.js +@@ -0,0 +1,861 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const GObject = imports.gi.GObject; ++const Gtk = imports.gi.Gtk; ++const Gdk = imports.gi.Gdk; ++const Mainloop = imports.mainloop; ++ ++// Use __ () and N__() for the extension gettext domain, and reuse ++// the shell domain with the default _() and N_() ++const Gettext = imports.gettext.domain('dashtodock'); ++const __ = Gettext.gettext; ++const N__ = function(e) { return e }; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++ ++const SCALE_UPDATE_TIMEOUT = 500; ++const DEFAULT_ICONS_SIZES = [ 128, 96, 64, 48, 32, 24, 16 ]; ++ ++const TransparencyMode = { ++ DEFAULT: 0, ++ FIXED: 1, ++ DYNAMIC: 3 ++}; ++ ++const RunningIndicatorStyle = { ++ DEFAULT: 0, ++ DOTS: 1, ++ SQUARES: 2, ++ DASHES: 3, ++ SEGMENTED: 4, ++ SOLID: 5, ++ CILIORA: 6, ++ METRO: 7 ++}; ++ ++/** ++ * This function was copied from the activities-config extension ++ * https://github.com/nls1729/acme-code/tree/master/activities-config ++ * by Norman L. Smith. ++ */ ++function cssHexString(css) { ++ let rrggbb = '#'; ++ let start; ++ for (let loop = 0; loop < 3; loop++) { ++ let end = 0; ++ let xx = ''; ++ for (let loop = 0; loop < 2; loop++) { ++ while (true) { ++ let x = css.slice(end, end + 1); ++ if ((x == '(') || (x == ',') || (x == ')')) ++ break; ++ end++; ++ } ++ if (loop == 0) { ++ end++; ++ start = end; ++ } ++ } ++ xx = parseInt(css.slice(start, end)).toString(16); ++ if (xx.length == 1) ++ xx = '0' + xx; ++ rrggbb += xx; ++ css = css.slice(end); ++ } ++ return rrggbb; ++} ++ ++function setShortcut(settings) { ++ let shortcut_text = settings.get_string('shortcut-text'); ++ let [key, mods] = Gtk.accelerator_parse(shortcut_text); ++ ++ if (Gtk.accelerator_valid(key, mods)) { ++ let shortcut = Gtk.accelerator_name(key, mods); ++ settings.set_strv('shortcut', [shortcut]); ++ } ++ else { ++ settings.set_strv('shortcut', []); ++ } ++} ++ ++var Settings = class DashToDock_Settings { ++ ++ constructor() { ++ this._settings = ExtensionUtils.getSettings('org.gnome.shell.extensions.dash-to-dock'); ++ ++ this._rtl = (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL); ++ ++ this._builder = new Gtk.Builder(); ++ this._builder.set_translation_domain(Me.metadata['gettext-domain']); ++ this._builder.add_from_file(Me.path + '/Settings.ui'); ++ ++ this.widget = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER }); ++ this._notebook = this._builder.get_object('settings_notebook'); ++ this.widget.add(this._notebook); ++ ++ // Set a reasonable initial window height ++ this.widget.connect('realize', () => { ++ let window = this.widget.get_toplevel(); ++ let [default_width, default_height] = window.get_default_size(); ++ window.resize(default_width, 650); ++ }); ++ ++ // Timeout to delay the update of the settings ++ this._dock_size_timeout = 0; ++ this._icon_size_timeout = 0; ++ this._opacity_timeout = 0; ++ ++ this._bindSettings(); ++ ++ this._builder.connect_signals_full(this._connector.bind(this)); ++ } ++ ++ /** ++ * Connect signals ++ */ ++ _connector(builder, object, signal, handler) { ++ /**init ++ * Object containing all signals defined in the glade file ++ */ ++ const SignalHandler = { ++ dock_display_combo_changed_cb(combo) { ++ this._settings.set_int('preferred-monitor', this._monitors[combo.get_active()]); ++ }, ++ ++ position_top_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('dock-position', 0); ++ }, ++ ++ position_right_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('dock-position', 1); ++ }, ++ ++ position_bottom_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('dock-position', 2); ++ }, ++ ++ position_left_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('dock-position', 3); ++ }, ++ ++ icon_size_combo_changed_cb(combo) { ++ this._settings.set_int('dash-max-icon-size', this._allIconSizes[combo.get_active()]); ++ }, ++ ++ dock_size_scale_format_value_cb(scale, value) { ++ return Math.round(value * 100) + ' %'; ++ }, ++ ++ dock_size_scale_value_changed_cb(scale) { ++ // Avoid settings the size consinuosly ++ if (this._dock_size_timeout > 0) ++ Mainloop.source_remove(this._dock_size_timeout); ++ ++ this._dock_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, () => { ++ this._settings.set_double('height-fraction', scale.get_value()); ++ this._dock_size_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ }, ++ ++ icon_size_scale_format_value_cb(scale, value) { ++ return value + ' px'; ++ }, ++ ++ icon_size_scale_value_changed_cb(scale) { ++ // Avoid settings the size consinuosly ++ if (this._icon_size_timeout > 0) ++ Mainloop.source_remove(this._icon_size_timeout); ++ ++ this._icon_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, () => { ++ this._settings.set_int('dash-max-icon-size', scale.get_value()); ++ this._icon_size_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ }, ++ ++ custom_opacity_scale_value_changed_cb(scale) { ++ // Avoid settings the opacity consinuosly as it's change is animated ++ if (this._opacity_timeout > 0) ++ Mainloop.source_remove(this._opacity_timeout); ++ ++ this._opacity_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, () => { ++ this._settings.set_double('background-opacity', scale.get_value()); ++ this._opacity_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ }, ++ ++ min_opacity_scale_value_changed_cb(scale) { ++ // Avoid settings the opacity consinuosly as it's change is animated ++ if (this._opacity_timeout > 0) ++ Mainloop.source_remove(this._opacity_timeout); ++ ++ this._opacity_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, () => { ++ this._settings.set_double('min-alpha', scale.get_value()); ++ this._opacity_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ }, ++ ++ max_opacity_scale_value_changed_cb(scale) { ++ // Avoid settings the opacity consinuosly as it's change is animated ++ if (this._opacity_timeout > 0) ++ Mainloop.source_remove(this._opacity_timeout); ++ ++ this._opacity_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, () => { ++ this._settings.set_double('max-alpha', scale.get_value()); ++ this._opacity_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ }, ++ ++ custom_opacity_scale_format_value_cb(scale, value) { ++ return Math.round(value * 100) + ' %'; ++ }, ++ ++ min_opacity_scale_format_value_cb(scale, value) { ++ return Math.round(value * 100) + ' %'; ++ }, ++ ++ max_opacity_scale_format_value_cb(scale, value) { ++ return Math.round(value * 100) + ' %'; ++ }, ++ ++ all_windows_radio_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('intellihide-mode', 0); ++ }, ++ ++ focus_application_windows_radio_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('intellihide-mode', 1); ++ }, ++ ++ maximized_windows_radio_button_toggled_cb(button) { ++ if (button.get_active()) ++ this._settings.set_enum('intellihide-mode', 2); ++ } ++ } ++ ++ object.connect(signal, SignalHandler[handler].bind(this)); ++ } ++ ++ _bindSettings() { ++ // Position and size panel ++ ++ // Monitor options ++ ++ this._monitors = []; ++ // Build options based on the number of monitors and the current settings. ++ let n_monitors = Gdk.Screen.get_default().get_n_monitors(); ++ let primary_monitor = Gdk.Screen.get_default().get_primary_monitor(); ++ ++ let monitor = this._settings.get_int('preferred-monitor'); ++ ++ // Add primary monitor with index 0, because in GNOME Shell the primary monitor is always 0 ++ this._builder.get_object('dock_monitor_combo').append_text(__('Primary monitor')); ++ this._monitors.push(0); ++ ++ // Add connected monitors ++ let ctr = 0; ++ for (let i = 0; i < n_monitors; i++) { ++ if (i !== primary_monitor) { ++ ctr++; ++ this._monitors.push(ctr); ++ this._builder.get_object('dock_monitor_combo').append_text(__('Secondary monitor ') + ctr); ++ } ++ } ++ ++ // If one of the external monitor is set as preferred, show it even if not attached ++ if ((monitor >= n_monitors) && (monitor !== primary_monitor)) { ++ this._monitors.push(monitor) ++ this._builder.get_object('dock_monitor_combo').append_text(__('Secondary monitor ') + ++ctr); ++ } ++ ++ this._builder.get_object('dock_monitor_combo').set_active(this._monitors.indexOf(monitor)); ++ ++ // Position option ++ let position = this._settings.get_enum('dock-position'); ++ ++ switch (position) { ++ case 0: ++ this._builder.get_object('position_top_button').set_active(true); ++ break; ++ case 1: ++ this._builder.get_object('position_right_button').set_active(true); ++ break; ++ case 2: ++ this._builder.get_object('position_bottom_button').set_active(true); ++ break; ++ case 3: ++ this._builder.get_object('position_left_button').set_active(true); ++ break; ++ } ++ ++ if (this._rtl) { ++ /* Left is Right in rtl as a setting */ ++ this._builder.get_object('position_left_button').set_label(__('Right')); ++ this._builder.get_object('position_right_button').set_label(__('Left')); ++ } ++ ++ // Intelligent autohide options ++ this._settings.bind('dock-fixed', ++ this._builder.get_object('intelligent_autohide_switch'), ++ 'active', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ this._settings.bind('dock-fixed', ++ this._builder.get_object('intelligent_autohide_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ this._settings.bind('autohide', ++ this._builder.get_object('autohide_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('autohide-in-fullscreen', ++ this._builder.get_object('autohide_enable_in_fullscreen_checkbutton'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('require-pressure-to-show', ++ this._builder.get_object('require_pressure_checkbutton'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('intellihide', ++ this._builder.get_object('intellihide_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('animation-time', ++ this._builder.get_object('animation_duration_spinbutton'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('hide-delay', ++ this._builder.get_object('hide_timeout_spinbutton'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-delay', ++ this._builder.get_object('show_timeout_spinbutton'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('pressure-threshold', ++ this._builder.get_object('pressure_threshold_spinbutton'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ //this._builder.get_object('animation_duration_spinbutton').set_value(this._settings.get_double('animation-time')); ++ ++ // Create dialog for intelligent autohide advanced settings ++ this._builder.get_object('intelligent_autohide_button').connect('clicked', () => { ++ ++ let dialog = new Gtk.Dialog({ title: __('Intelligent autohide customization'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(__('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('intelligent_autohide_advanced_settings_box'); ++ dialog.get_content_area().add(box); ++ ++ this._settings.bind('intellihide', ++ this._builder.get_object('intellihide_mode_box'), ++ 'sensitive', ++ Gio.SettingsBindFlags.GET); ++ ++ // intellihide mode ++ ++ let intellihideModeRadioButtons = [ ++ this._builder.get_object('all_windows_radio_button'), ++ this._builder.get_object('focus_application_windows_radio_button'), ++ this._builder.get_object('maximized_windows_radio_button') ++ ]; ++ ++ intellihideModeRadioButtons[this._settings.get_enum('intellihide-mode')].set_active(true); ++ ++ this._settings.bind('autohide', ++ this._builder.get_object('require_pressure_checkbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.GET); ++ ++ this._settings.bind('autohide', ++ this._builder.get_object('autohide_enable_in_fullscreen_checkbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.GET); ++ ++ this._settings.bind('require-pressure-to-show', ++ this._builder.get_object('show_timeout_spinbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ this._settings.bind('require-pressure-to-show', ++ this._builder.get_object('show_timeout_label'), ++ 'sensitive', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ this._settings.bind('require-pressure-to-show', ++ this._builder.get_object('pressure_threshold_spinbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('require-pressure-to-show', ++ this._builder.get_object('pressure_threshold_label'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ dialog.connect('response', (dialog, id) => { ++ if (id == 1) { ++ // restore default settings for the relevant keys ++ let keys = ['intellihide', 'autohide', 'intellihide-mode', 'autohide-in-fullscreen', 'require-pressure-to-show', ++ 'animation-time', 'show-delay', 'hide-delay', 'pressure-threshold']; ++ keys.forEach(function(val) { ++ this._settings.set_value(val, this._settings.get_default_value(val)); ++ }, this); ++ intellihideModeRadioButtons[this._settings.get_enum('intellihide-mode')].set_active(true); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ }); ++ ++ dialog.show_all(); ++ ++ }); ++ ++ // size options ++ this._builder.get_object('dock_size_scale').set_value(this._settings.get_double('height-fraction')); ++ this._builder.get_object('dock_size_scale').add_mark(0.9, Gtk.PositionType.TOP, null); ++ let icon_size_scale = this._builder.get_object('icon_size_scale'); ++ icon_size_scale.set_range(8, DEFAULT_ICONS_SIZES[0]); ++ icon_size_scale.set_value(this._settings.get_int('dash-max-icon-size')); ++ DEFAULT_ICONS_SIZES.forEach(function(val) { ++ icon_size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString()); ++ }); ++ ++ // Corrent for rtl languages ++ if (this._rtl) { ++ // Flip value position: this is not done automatically ++ this._builder.get_object('dock_size_scale').set_value_pos(Gtk.PositionType.LEFT); ++ icon_size_scale.set_value_pos(Gtk.PositionType.LEFT); ++ // I suppose due to a bug, having a more than one mark and one above a value of 100 ++ // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable ++ // and then manually inverting it ++ icon_size_scale.set_flippable(false); ++ icon_size_scale.set_inverted(true); ++ } ++ ++ this._settings.bind('icon-size-fixed', this._builder.get_object('icon_size_fixed_checkbutton'), 'active', Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('extend-height', this._builder.get_object('dock_size_extend_checkbutton'), 'active', Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('extend-height', this._builder.get_object('dock_size_scale'), 'sensitive', Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ ++ ++ // Apps panel ++ ++ this._settings.bind('show-running', ++ this._builder.get_object('show_running_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('isolate-workspaces', ++ this._builder.get_object('application_button_isolation_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('isolate-monitors', ++ this._builder.get_object('application_button_monitor_isolation_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-windows-preview', ++ this._builder.get_object('windows_preview_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('multi-monitor', ++ this._builder.get_object('multi_monitor_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-favorites', ++ this._builder.get_object('show_favorite_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-show-apps-button', ++ this._builder.get_object('show_applications_button_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-apps-at-top', ++ this._builder.get_object('application_button_first_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-show-apps-button', ++ this._builder.get_object('application_button_first_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('animate-show-apps', ++ this._builder.get_object('application_button_animation_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('show-show-apps-button', ++ this._builder.get_object('application_button_animation_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ ++ // Behavior panel ++ ++ this._settings.bind('hot-keys', ++ this._builder.get_object('hot_keys_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('hot-keys', ++ this._builder.get_object('overlay_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('click_action_combo').set_active(this._settings.get_enum('click-action')); ++ this._builder.get_object('click_action_combo').connect('changed', (widget) => { ++ this._settings.set_enum('click-action', widget.get_active()); ++ }); ++ ++ this._builder.get_object('scroll_action_combo').set_active(this._settings.get_enum('scroll-action')); ++ this._builder.get_object('scroll_action_combo').connect('changed', (widget) => { ++ this._settings.set_enum('scroll-action', widget.get_active()); ++ }); ++ ++ this._builder.get_object('shift_click_action_combo').connect('changed', (widget) => { ++ this._settings.set_enum('shift-click-action', widget.get_active()); ++ }); ++ ++ this._builder.get_object('middle_click_action_combo').connect('changed', (widget) => { ++ this._settings.set_enum('middle-click-action', widget.get_active()); ++ }); ++ this._builder.get_object('shift_middle_click_action_combo').connect('changed', (widget) => { ++ this._settings.set_enum('shift-middle-click-action', widget.get_active()); ++ }); ++ ++ // Create dialog for number overlay options ++ this._builder.get_object('overlay_button').connect('clicked', () => { ++ ++ let dialog = new Gtk.Dialog({ title: __('Show dock and application numbers'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(__('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_overlay_shortcut'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('overlay_switch').set_active(this._settings.get_boolean('hotkeys-overlay')); ++ this._builder.get_object('show_dock_switch').set_active(this._settings.get_boolean('hotkeys-show-dock')); ++ ++ // We need to update the shortcut 'strv' when the text is modified ++ this._settings.connect('changed::shortcut-text', () => {setShortcut(this._settings);}); ++ this._settings.bind('shortcut-text', ++ this._builder.get_object('shortcut_entry'), ++ 'text', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('hotkeys-overlay', ++ this._builder.get_object('overlay_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('hotkeys-show-dock', ++ this._builder.get_object('show_dock_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('shortcut-timeout', ++ this._builder.get_object('timeout_spinbutton'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ dialog.connect('response', (dialog, id) => { ++ if (id == 1) { ++ // restore default settings for the relevant keys ++ let keys = ['shortcut-text', 'hotkeys-overlay', 'hotkeys-show-dock', 'shortcut-timeout']; ++ keys.forEach(function(val) { ++ this._settings.set_value(val, this._settings.get_default_value(val)); ++ }, this); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ }); ++ ++ dialog.show_all(); ++ }); ++ ++ // Create dialog for middle-click options ++ this._builder.get_object('middle_click_options_button').connect('clicked', () => { ++ ++ let dialog = new Gtk.Dialog({ title: __('Customize middle-click behavior'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(__('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_middle_click_options'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('shift_click_action_combo').set_active(this._settings.get_enum('shift-click-action')); ++ ++ this._builder.get_object('middle_click_action_combo').set_active(this._settings.get_enum('middle-click-action')); ++ ++ this._builder.get_object('shift_middle_click_action_combo').set_active(this._settings.get_enum('shift-middle-click-action')); ++ ++ this._settings.bind('shift-click-action', ++ this._builder.get_object('shift_click_action_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('middle-click-action', ++ this._builder.get_object('middle_click_action_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('shift-middle-click-action', ++ this._builder.get_object('shift_middle_click_action_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ dialog.connect('response', (dialog, id) => { ++ if (id == 1) { ++ // restore default settings for the relevant keys ++ let keys = ['shift-click-action', 'middle-click-action', 'shift-middle-click-action']; ++ keys.forEach(function(val) { ++ this._settings.set_value(val, this._settings.get_default_value(val)); ++ }, this); ++ this._builder.get_object('shift_click_action_combo').set_active(this._settings.get_enum('shift-click-action')); ++ this._builder.get_object('middle_click_action_combo').set_active(this._settings.get_enum('middle-click-action')); ++ this._builder.get_object('shift_middle_click_action_combo').set_active(this._settings.get_enum('shift-middle-click-action')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ }); ++ ++ dialog.show_all(); ++ ++ }); ++ ++ // Appearance Panel ++ ++ this._settings.bind('apply-custom-theme', this._builder.get_object('customize_theme'), 'sensitive', Gio.SettingsBindFlags.INVERT_BOOLEAN | Gio.SettingsBindFlags.GET); ++ this._settings.bind('apply-custom-theme', this._builder.get_object('builtin_theme_switch'), 'active', Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('custom-theme-shrink', this._builder.get_object('shrink_dash_switch'), 'active', Gio.SettingsBindFlags.DEFAULT); ++ ++ // Running indicators ++ this._builder.get_object('running_indicators_combo').set_active( ++ this._settings.get_enum('running-indicator-style') ++ ); ++ this._builder.get_object('running_indicators_combo').connect( ++ 'changed', ++ (widget) => { ++ this._settings.set_enum('running-indicator-style', widget.get_active()); ++ } ++ ); ++ ++ if (this._settings.get_enum('running-indicator-style') == RunningIndicatorStyle.DEFAULT) ++ this._builder.get_object('running_indicators_advance_settings_button').set_sensitive(false); ++ ++ this._settings.connect('changed::running-indicator-style', () => { ++ if (this._settings.get_enum('running-indicator-style') == RunningIndicatorStyle.DEFAULT) ++ this._builder.get_object('running_indicators_advance_settings_button').set_sensitive(false); ++ else ++ this._builder.get_object('running_indicators_advance_settings_button').set_sensitive(true); ++ }); ++ ++ // Create dialog for running indicators advanced settings ++ this._builder.get_object('running_indicators_advance_settings_button').connect('clicked', () => { ++ ++ let dialog = new Gtk.Dialog({ title: __('Customize running indicators'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ let box = this._builder.get_object('running_dots_advance_settings_box'); ++ dialog.get_content_area().add(box); ++ ++ this._settings.bind('running-indicator-dominant-color', ++ this._builder.get_object('dominant_color_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('custom-theme-customize-running-dots', ++ this._builder.get_object('dot_style_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('custom-theme-customize-running-dots', ++ this._builder.get_object('dot_style_settings_box'), ++ 'sensitive', Gio.SettingsBindFlags.DEFAULT); ++ ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('custom-theme-running-dots-color')); ++ this._builder.get_object('dot_color_colorbutton').set_rgba(rgba); ++ ++ this._builder.get_object('dot_color_colorbutton').connect('notify::color', (button) => { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('custom-theme-running-dots-color', hexString); ++ }); ++ ++ rgba.parse(this._settings.get_string('custom-theme-running-dots-border-color')); ++ this._builder.get_object('dot_border_color_colorbutton').set_rgba(rgba); ++ ++ this._builder.get_object('dot_border_color_colorbutton').connect('notify::color', (button) => { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('custom-theme-running-dots-border-color', hexString); ++ }); ++ ++ this._settings.bind('custom-theme-running-dots-border-width', ++ this._builder.get_object('dot_border_width_spin_button'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ ++ dialog.connect('response', (dialog, id) => { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ return; ++ }); ++ ++ dialog.show_all(); ++ ++ }); ++ ++ this._settings.bind('custom-background-color', this._builder.get_object('custom_background_color_switch'), 'active', Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('custom-background-color', this._builder.get_object('custom_background_color'), 'sensitive', Gio.SettingsBindFlags.DEFAULT); ++ ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('background-color')); ++ this._builder.get_object('custom_background_color').set_rgba(rgba); ++ ++ this._builder.get_object('custom_background_color').connect('notify::color', (button) => { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('background-color', hexString); ++ }); ++ ++ // Opacity ++ this._builder.get_object('customize_opacity_combo').set_active( ++ this._settings.get_enum('transparency-mode') ++ ); ++ this._builder.get_object('customize_opacity_combo').connect( ++ 'changed', ++ (widget) => { ++ this._settings.set_enum('transparency-mode', widget.get_active()); ++ } ++ ); ++ ++ this._builder.get_object('custom_opacity_scale').set_value(this._settings.get_double('background-opacity')); ++ ++ if (this._settings.get_enum('transparency-mode') !== TransparencyMode.FIXED) ++ this._builder.get_object('custom_opacity_scale').set_sensitive(false); ++ ++ this._settings.connect('changed::transparency-mode', () => { ++ if (this._settings.get_enum('transparency-mode') !== TransparencyMode.FIXED) ++ this._builder.get_object('custom_opacity_scale').set_sensitive(false); ++ else ++ this._builder.get_object('custom_opacity_scale').set_sensitive(true); ++ }); ++ ++ if (this._settings.get_enum('transparency-mode') !== TransparencyMode.DYNAMIC) { ++ this._builder.get_object('dynamic_opacity_button').set_sensitive(false); ++ } ++ ++ this._settings.connect('changed::transparency-mode', () => { ++ if (this._settings.get_enum('transparency-mode') !== TransparencyMode.DYNAMIC) { ++ this._builder.get_object('dynamic_opacity_button').set_sensitive(false); ++ } ++ else { ++ this._builder.get_object('dynamic_opacity_button').set_sensitive(true); ++ } ++ }); ++ ++ // Create dialog for transparency advanced settings ++ this._builder.get_object('dynamic_opacity_button').connect('clicked', () => { ++ ++ let dialog = new Gtk.Dialog({ title: __('Cutomize opacity'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ let box = this._builder.get_object('advanced_transparency_dialog'); ++ dialog.get_content_area().add(box); ++ ++ this._settings.bind( ++ 'customize-alphas', ++ this._builder.get_object('customize_alphas_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT ++ ); ++ this._settings.bind( ++ 'customize-alphas', ++ this._builder.get_object('min_alpha_scale'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT ++ ); ++ this._settings.bind( ++ 'customize-alphas', ++ this._builder.get_object('max_alpha_scale'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT ++ ); ++ ++ this._builder.get_object('min_alpha_scale').set_value( ++ this._settings.get_double('min-alpha') ++ ); ++ this._builder.get_object('max_alpha_scale').set_value( ++ this._settings.get_double('max-alpha') ++ ); ++ ++ dialog.connect('response', (dialog, id) => { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ return; ++ }); ++ ++ dialog.show_all(); ++ }); ++ ++ ++ this._settings.bind('unity-backlit-items', ++ this._builder.get_object('unity_backlit_items_switch'), ++ 'active', Gio.SettingsBindFlags.DEFAULT ++ ); ++ ++ this._settings.bind('force-straight-corner', ++ this._builder.get_object('force_straight_corner_switch'), ++ 'active', Gio.SettingsBindFlags.DEFAULT); ++ ++ // About Panel ++ ++ this._builder.get_object('extension_version').set_label(Me.metadata.version.toString()); ++ } ++}; ++ ++function init() { ++ ExtensionUtils.initTranslations(); ++} ++ ++function buildPrefsWidget() { ++ let settings = new Settings(); ++ let widget = settings.widget; ++ widget.show_all(); ++ return widget; ++} +diff --git a/extensions/dash-to-dock/stylesheet.css b/extensions/dash-to-dock/stylesheet.css +new file mode 100644 +index 00000000..26cc960c +--- /dev/null ++++ b/extensions/dash-to-dock/stylesheet.css +@@ -0,0 +1,175 @@ ++/* Shrink the dash by reducing padding and border radius */ ++#dashtodockContainer.shrink #dash, ++#dashtodockContainer.dashtodock #dash { ++ border:1px; ++ padding:0px; ++} ++ ++#dashtodockContainer.shrink.left #dash, ++#dashtodockContainer.dashtodock.left #dash { ++ border-left: 0px; ++ border-radius: 0px 9px 9px 0px; ++} ++ ++ ++#dashtodockContainer.shrink.right #dash, ++#dashtodockContainer.dashtodock.right #dash { ++ border-right: 0px; ++ border-radius: 9px 0px 0px 9px; ++} ++ ++ ++#dashtodockContainer.shrink.top #dash, ++#dashtodockContainer.dashtodock.top #dash { ++ border-top: 0px; ++ border-radius: 0px 0px 9px 9px; ++} ++ ++#dashtodockContainer.shrink.bottom #dash, ++#dashtodockContainer.dashtodock.bottom #dash { ++ border-bottom: 0px; ++ border-radius: 9px 9px 0px 0px; ++} ++ ++#dashtodockContainer.straight-corner #dash, ++#dashtodockContainer.shrink.straight-corner #dash { ++ border-radius: 0px; ++} ++ ++/* Scrollview style */ ++.bottom #dashtodockDashScrollview, ++.top #dashtodockDashScrollview { ++ -st-hfade-offset: 24px; ++} ++ ++.left #dashtodockDashScrollview, ++.right #dashtodockDashScrollview { ++ -st-vfade-offset: 24px; ++} ++ ++#dashtodockContainer.running-dots .dash-item-container > StButton, ++#dashtodockContainer.dashtodock .dash-item-container > StButton { ++ transition-duration: 250; ++ background-size: contain; ++} ++ ++#dashtodockContainer.shrink .dash-item-container > StButton, ++#dashtodockContainer.dashtodock .dash-item-container > StButton { ++ padding: 1px 2px; ++} ++ ++/* Dash height extended to the whole available vertical space */ ++#dashtodockContainer.extended.top #dash, ++#dashtodockContainer.extended.right #dash, ++#dashtodockContainer.extended.bottom #dash, ++#dashtodockContainer.extended.left #dash { ++ border-radius: 0; ++} ++ ++#dashtodockContainer.extended.top #dash, ++#dashtodockContainer.extended.bottom #dash { ++ border-left:0px; ++ border-right:0px; ++} ++ ++#dashtodockContainer.extended.right #dash, ++#dashtodockContainer.extended.left #dash { ++ border-top:0px; ++ border-bottom:0px; ++} ++ ++/* Running and focused application style */ ++ ++#dashtodockContainer.running-dots .app-well-app.running > .overview-icon, ++#dashtodockContainer.dashtodock .app-well-app.running > .overview-icon { ++ background-image:none; ++} ++ ++ ++#dashtodockContainer.running-dots .app-well-app.focused .overview-icon, ++#dashtodockContainer.dashtodock .app-well-app.focused .overview-icon { ++ background-color: rgba(238, 238, 236, 0.2); ++} ++ ++#dashtodockContainer.dashtodock #dash { ++ background: #2e3436; ++} ++ ++/* ++ * This is applied to a dummy actor. Only the alpha value for the background and border color ++ * and the transition-duration are used ++ */ ++#dashtodockContainer.dummy-opaque { ++ background-color: rgba(0, 0, 0, 0.8); ++ border-color: rgba(0, 0, 0, 0.4); ++ transition-duration: 300ms; ++} ++ ++/* ++ * This is applied to a dummy actor. Only the alpha value for the background and border color ++ * and the transition-duration are used ++ */ ++#dashtodockContainer.dummy-transparent { ++ background-color: rgba(0, 0, 0, 0.2); ++ border-color: rgba(0, 0, 0, 0.1); ++ transition-duration: 500ms; ++} ++ ++#dashtodockContainer.opaque { ++} ++ ++#dashtodockContainer.transparent { ++} ++ ++#dashtodockContainer .number-overlay { ++ color: rgba(255,255,255,1); ++ background-color: rgba(0,0,0,0.8); ++ text-align: center; ++} ++ ++#dashtodockContainer .notification-badge { ++ color: rgba(255,255,255,1); ++ background-color: rgba(255,0,0,1.0); ++ padding: 0.2em 0.5em; ++ border-radius: 1em; ++ font-weight: bold; ++ text-align: center; ++ margin: 2px; ++} ++ ++#dashtodockPreviewSeparator.popup-separator-menu-item-horizontal { ++ width: 1px; ++ height: auto; ++ border-right-width: 1px; ++ margin: 32px 0px; ++} ++ ++.dashtodock-app-well-preview-menu-item { ++ padding: 1em 1em 0.5em 1em; ++} ++ ++#dashtodockContainer .metro .overview-icon{ ++ border-radius: 0px; ++} ++ ++#dashtodockContainer.bottom .metro.running2.focused, ++#dashtodockContainer.bottom .metro.running3.focused, ++#dashtodockContainer.bottom .metro.running4.focused, ++#dashtodockContainer.top .metro.running2.focused, ++#dashtodockContainer.top .metro.running3.focused, ++#dashtodockContainer.top .metro.running4.focused { ++ background-image: url('./media/highlight_stacked_bg.svg'); ++ background-position: 0px 0px; ++ background-size: contain; ++} ++ ++#dashtodockContainer.left .metro.running2.focused, ++#dashtodockContainer.left .metro.running3.focused, ++#dashtodockContainer.left .metro.running4.focused, ++#dashtodockContainer.right .metro.running2.focused, ++#dashtodockContainer.right .metro.running3.focused, ++#dashtodockContainer.right .metro.running4.focused { ++ background-image: url('./media/highlight_stacked_bg_h.svg'); ++ background-position: 0px 0px; ++ background-size: contain; ++} +\ No newline at end of file +diff --git a/extensions/dash-to-dock/theming.js b/extensions/dash-to-dock/theming.js +new file mode 100644 +index 00000000..596574d2 +--- /dev/null ++++ b/extensions/dash-to-dock/theming.js +@@ -0,0 +1,569 @@ ++// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- ++ ++const Clutter = imports.gi.Clutter; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Gtk = imports.gi.Gtk; ++const Signals = imports.signals; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++ ++const AppDisplay = imports.ui.appDisplay; ++const AppFavorites = imports.ui.appFavorites; ++const Dash = imports.ui.dash; ++const DND = imports.ui.dnd; ++const IconGrid = imports.ui.iconGrid; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; ++const Util = imports.misc.util; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Dock = Me.imports.docking; ++const Utils = Me.imports.utils; ++ ++/* ++ * DEFAULT: transparency given by theme ++ * FIXED: constant transparency chosen by user ++ * DYNAMIC: apply 'transparent' style when no windows are close to the dock ++ * */ ++const TransparencyMode = { ++ DEFAULT: 0, ++ FIXED: 1, ++ DYNAMIC: 3 ++}; ++ ++/** ++ * Manage theme customization and custom theme support ++ */ ++var ThemeManager = class DashToDock_ThemeManager { ++ ++ constructor(settings, dock) { ++ this._settings = settings; ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._bindSettingsChanges(); ++ this._actor = dock.actor; ++ this._dash = dock.dash; ++ ++ // initialize colors with generic values ++ this._customizedBackground = {red: 0, green: 0, blue: 0, alpha: 0}; ++ this._customizedBorder = {red: 0, green: 0, blue: 0, alpha: 0}; ++ this._transparency = new Transparency(this._settings, dock); ++ ++ this._signalsHandler.add([ ++ // When theme changes re-obtain default background color ++ St.ThemeContext.get_for_stage (global.stage), ++ 'changed', ++ this.updateCustomTheme.bind(this) ++ ], [ ++ // update :overview pseudoclass ++ Main.overview, ++ 'showing', ++ this._onOverviewShowing.bind(this) ++ ], [ ++ Main.overview, ++ 'hiding', ++ this._onOverviewHiding.bind(this) ++ ]); ++ ++ this._updateCustomStyleClasses(); ++ ++ // destroy themeManager when the managed actor is destroyed (e.g. extension unload) ++ // in order to disconnect signals ++ this._actor.connect('destroy', this.destroy.bind(this)); ++ ++ } ++ ++ destroy() { ++ this._signalsHandler.destroy(); ++ this._transparency.destroy(); ++ } ++ ++ _onOverviewShowing() { ++ this._actor.add_style_pseudo_class('overview'); ++ } ++ ++ _onOverviewHiding() { ++ this._actor.remove_style_pseudo_class('overview'); ++ } ++ ++ _updateDashOpacity() { ++ let newAlpha = this._settings.get_double('background-opacity'); ++ ++ let [backgroundColor, borderColor] = this._getDefaultColors(); ++ ++ if (backgroundColor==null) ++ return; ++ ++ // Get the background and border alphas. We check the background alpha ++ // for a minimum of .001 to prevent division by 0 errors ++ let backgroundAlpha = Math.max(Math.round(backgroundColor.alpha/2.55)/100, .001); ++ let borderAlpha = Math.round(borderColor.alpha/2.55)/100; ++ ++ // The border and background alphas should remain in sync ++ // We also limit the borderAlpha to a maximum of 1 (full opacity) ++ borderAlpha = Math.min((borderAlpha/backgroundAlpha)*newAlpha, 1); ++ ++ this._customizedBackground = 'rgba(' + ++ backgroundColor.red + ',' + ++ backgroundColor.green + ',' + ++ backgroundColor.blue + ',' + ++ newAlpha + ')'; ++ ++ this._customizedBorder = 'rgba(' + ++ borderColor.red + ',' + ++ borderColor.green + ',' + ++ borderColor.blue + ',' + ++ borderAlpha + ')'; ++ ++ } ++ ++ _getDefaultColors() { ++ // Prevent shell crash if the actor is not on the stage. ++ // It happens enabling/disabling repeatedly the extension ++ if (!this._dash._container.get_stage()) ++ return [null, null]; ++ ++ // Remove custom style ++ let oldStyle = this._dash._container.get_style(); ++ this._dash._container.set_style(null); ++ ++ let themeNode = this._dash._container.get_theme_node(); ++ this._dash._container.set_style(oldStyle); ++ ++ let backgroundColor = themeNode.get_background_color(); ++ ++ // Just in case the theme has different border colors .. ++ // We want to find the inside border-color of the dock because it is ++ // the side most visible to the user. We do this by finding the side ++ // opposite the position ++ let position = Utils.getPosition(this._settings); ++ let side = position + 2; ++ if (side > 3) ++ side = Math.abs(side - 4); ++ ++ let borderColor = themeNode.get_border_color(side); ++ ++ return [backgroundColor, borderColor]; ++ } ++ ++ _updateDashColor() { ++ // Retrieve the color. If needed we will adjust it before passing it to ++ // this._transparency. ++ let [backgroundColor, borderColor] = this._getDefaultColors(); ++ ++ if (backgroundColor==null) ++ return; ++ ++ if (this._settings.get_boolean('custom-background-color')) { ++ // When applying a custom color, we need to check the alpha value, ++ // if not the opacity will always be overridden by the color below. ++ // Note that if using 'dynamic' transparency modes, ++ // the opacity will be set by the opaque/transparent styles anyway. ++ let newAlpha = Math.round(backgroundColor.alpha/2.55)/100; ++ if (this._settings.get_enum('transparency-mode') == TransparencyMode.FIXED) ++ newAlpha = this._settings.get_double('background-opacity'); ++ ++ backgroundColor = Clutter.color_from_string(this._settings.get_string('background-color'))[1]; ++ this._customizedBackground = 'rgba(' + ++ backgroundColor.red + ',' + ++ backgroundColor.green + ',' + ++ backgroundColor.blue + ',' + ++ newAlpha + ')'; ++ ++ this._customizedBorder = this._customizedBackground; ++ } ++ this._transparency.setColor(backgroundColor); ++ } ++ ++ _updateCustomStyleClasses() { ++ if (this._settings.get_boolean('apply-custom-theme')) ++ this._actor.add_style_class_name('dashtodock'); ++ else ++ this._actor.remove_style_class_name('dashtodock'); ++ ++ if (this._settings.get_boolean('custom-theme-shrink')) ++ this._actor.add_style_class_name('shrink'); ++ else ++ this._actor.remove_style_class_name('shrink'); ++ ++ if (this._settings.get_enum('running-indicator-style') !== 0) ++ this._actor.add_style_class_name('running-dots'); ++ else ++ this._actor.remove_style_class_name('running-dots'); ++ ++ // If not the built-in theme option is not selected ++ if (!this._settings.get_boolean('apply-custom-theme')) { ++ if (this._settings.get_boolean('force-straight-corner')) ++ this._actor.add_style_class_name('straight-corner'); ++ else ++ this._actor.remove_style_class_name('straight-corner'); ++ } else { ++ this._actor.remove_style_class_name('straight-corner'); ++ } ++ } ++ ++ updateCustomTheme() { ++ this._updateCustomStyleClasses(); ++ this._updateDashOpacity(); ++ this._updateDashColor(); ++ this._adjustTheme(); ++ this._dash._redisplay(); ++ } ++ ++ /** ++ * Reimported back and adapted from atomdock ++ */ ++ _adjustTheme() { ++ // Prevent shell crash if the actor is not on the stage. ++ // It happens enabling/disabling repeatedly the extension ++ if (!this._dash._container.get_stage()) ++ return; ++ ++ // Remove prior style edits ++ this._dash._container.set_style(null); ++ this._transparency.disable(); ++ ++ // If built-in theme is enabled do nothing else ++ if (this._settings.get_boolean('apply-custom-theme')) ++ return; ++ ++ let newStyle = ''; ++ let position = Utils.getPosition(this._settings); ++ ++ if (!this._settings.get_boolean('custom-theme-shrink')) { ++ // obtain theme border settings ++ let themeNode = this._dash._container.get_theme_node(); ++ let borderColor = themeNode.get_border_color(St.Side.TOP); ++ let borderWidth = themeNode.get_border_width(St.Side.TOP); ++ let borderRadius = themeNode.get_border_radius(St.Corner.TOPRIGHT); ++ ++ // We're copying border and corner styles to left border and top-left ++ // corner, also removing bottom border and bottom-right corner styles ++ let borderInner = ''; ++ let borderRadiusValue = ''; ++ let borderMissingStyle = ''; ++ ++ if (this._rtl && (position != St.Side.RIGHT)) ++ borderMissingStyle = 'border-right: ' + borderWidth + 'px solid ' + ++ borderColor.to_string() + ';'; ++ else if (!this._rtl && (position != St.Side.LEFT)) ++ borderMissingStyle = 'border-left: ' + borderWidth + 'px solid ' + ++ borderColor.to_string() + ';'; ++ ++ switch (position) { ++ case St.Side.LEFT: ++ borderInner = 'border-left'; ++ borderRadiusValue = '0 ' + borderRadius + 'px ' + borderRadius + 'px 0;'; ++ break; ++ case St.Side.RIGHT: ++ borderInner = 'border-right'; ++ borderRadiusValue = borderRadius + 'px 0 0 ' + borderRadius + 'px;'; ++ break; ++ case St.Side.TOP: ++ borderInner = 'border-top'; ++ borderRadiusValue = '0 0 ' + borderRadius + 'px ' + borderRadius + 'px;'; ++ break; ++ case St.Side.BOTTOM: ++ borderInner = 'border-bottom'; ++ borderRadiusValue = borderRadius + 'px ' + borderRadius + 'px 0 0;'; ++ break; ++ } ++ ++ newStyle = borderInner + ': none;' + ++ 'border-radius: ' + borderRadiusValue + ++ borderMissingStyle; ++ ++ // I do call set_style possibly twice so that only the background gets the transition. ++ // The transition-property css rules seems to be unsupported ++ this._dash._container.set_style(newStyle); ++ } ++ ++ // Customize background ++ let fixedTransparency = this._settings.get_enum('transparency-mode') == TransparencyMode.FIXED; ++ let defaultTransparency = this._settings.get_enum('transparency-mode') == TransparencyMode.DEFAULT; ++ if (!defaultTransparency && !fixedTransparency) { ++ this._transparency.enable(); ++ } ++ else if (!defaultTransparency || this._settings.get_boolean('custom-background-color')) { ++ newStyle = newStyle + 'background-color:'+ this._customizedBackground + '; ' + ++ 'border-color:'+ this._customizedBorder + '; ' + ++ 'transition-delay: 0s; transition-duration: 0.250s;'; ++ this._dash._container.set_style(newStyle); ++ } ++ } ++ ++ _bindSettingsChanges() { ++ let keys = ['transparency-mode', ++ 'customize-alphas', ++ 'min-alpha', ++ 'max-alpha', ++ 'background-opacity', ++ 'custom-background-color', ++ 'background-color', ++ 'apply-custom-theme', ++ 'custom-theme-shrink', ++ 'custom-theme-running-dots', ++ 'extend-height', ++ 'force-straight-corner']; ++ ++ keys.forEach(function(key) { ++ this._signalsHandler.add([ ++ this._settings, ++ 'changed::' + key, ++ this.updateCustomTheme.bind(this) ++ ]); ++ }, this); ++ } ++}; ++ ++/** ++ * The following class is based on the following upstream commit: ++ * https://git.gnome.org/browse/gnome-shell/commit/?id=447bf55e45b00426ed908b1b1035f472c2466956 ++ * Transparency when free-floating ++ */ ++var Transparency = class DashToDock_Transparency { ++ ++ constructor(settings, dock) { ++ this._settings = settings; ++ this._dash = dock.dash; ++ this._actor = this._dash._container; ++ this._dockActor = dock.actor; ++ this._dock = dock; ++ this._panel = Main.panel; ++ this._position = Utils.getPosition(this._settings); ++ ++ // All these properties are replaced with the ones in the .dummy-opaque and .dummy-transparent css classes ++ this._backgroundColor = '0,0,0'; ++ this._transparentAlpha = '0.2'; ++ this._opaqueAlpha = '1'; ++ this._transparentAlphaBorder = '0.1'; ++ this._opaqueAlphaBorder = '0.5'; ++ this._transparentTransition = '0ms'; ++ this._opaqueTransition = '0ms'; ++ this._base_actor_style = ""; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._injectionsHandler = new Utils.InjectionsHandler(); ++ this._trackedWindows = new Map(); ++ } ++ ++ enable() { ++ // ensure I never double-register/inject ++ // although it should never happen ++ this.disable(); ++ ++ this._base_actor_style = this._actor.get_style(); ++ if (this._base_actor_style == null) { ++ this._base_actor_style = ""; ++ } ++ ++ this._signalsHandler.addWithLabel('transparency', [ ++ global.window_group, ++ 'actor-added', ++ this._onWindowActorAdded.bind(this) ++ ], [ ++ global.window_group, ++ 'actor-removed', ++ this._onWindowActorRemoved.bind(this) ++ ], [ ++ global.window_manager, ++ 'switch-workspace', ++ this._updateSolidStyle.bind(this) ++ ], [ ++ Main.overview, ++ 'hiding', ++ this._updateSolidStyle.bind(this) ++ ], [ ++ Main.overview, ++ 'showing', ++ this._updateSolidStyle.bind(this) ++ ]); ++ ++ // Window signals ++ global.window_group.get_children().filter(function(child) { ++ // An irrelevant window actor ('Gnome-shell') produces an error when the signals are ++ // disconnected, therefore do not add signals to it. ++ return child instanceof Meta.WindowActor && ++ child.get_meta_window().get_wm_class() !== 'Gnome-shell'; ++ }).forEach(function(win) { ++ this._onWindowActorAdded(null, win); ++ }, this); ++ ++ if (this._actor.get_stage()) ++ this._updateSolidStyle(); ++ ++ this._updateStyles(); ++ this._updateSolidStyle(); ++ ++ this.emit('transparency-enabled'); ++ } ++ ++ disable() { ++ // ensure I never double-register/inject ++ // although it should never happen ++ this._signalsHandler.removeWithLabel('transparency'); ++ ++ for (let key of this._trackedWindows.keys()) ++ this._trackedWindows.get(key).forEach(id => { ++ key.disconnect(id); ++ }); ++ this._trackedWindows.clear(); ++ ++ this.emit('transparency-disabled'); ++ } ++ ++ destroy() { ++ this.disable(); ++ this._signalsHandler.destroy(); ++ this._injectionsHandler.destroy(); ++ } ++ ++ _onWindowActorAdded(container, metaWindowActor) { ++ let signalIds = []; ++ ['allocation-changed', 'notify::visible'].forEach(s => { ++ signalIds.push(metaWindowActor.connect(s, this._updateSolidStyle.bind(this))); ++ }); ++ this._trackedWindows.set(metaWindowActor, signalIds); ++ } ++ ++ _onWindowActorRemoved(container, metaWindowActor) { ++ if (!this._trackedWindows.get(metaWindowActor)) ++ return; ++ ++ this._trackedWindows.get(metaWindowActor).forEach(id => { ++ metaWindowActor.disconnect(id); ++ }); ++ this._trackedWindows.delete(metaWindowActor); ++ this._updateSolidStyle(); ++ } ++ ++ _updateSolidStyle() { ++ let isNear = this._dockIsNear(); ++ if (isNear) { ++ this._actor.set_style(this._opaque_style); ++ this._dockActor.remove_style_class_name('transparent'); ++ this._dockActor.add_style_class_name('opaque'); ++ } ++ else { ++ this._actor.set_style(this._transparent_style); ++ this._dockActor.remove_style_class_name('opaque'); ++ this._dockActor.add_style_class_name('transparent'); ++ } ++ ++ this.emit('solid-style-updated', isNear); ++ } ++ ++ _dockIsNear() { ++ if (this._dockActor.has_style_pseudo_class('overview')) ++ return false; ++ /* Get all the windows in the active workspace that are in the primary monitor and visible */ ++ let activeWorkspace = global.workspace_manager.get_active_workspace(); ++ let dash = this._dash; ++ let windows = activeWorkspace.list_windows().filter(function(metaWindow) { ++ return metaWindow.get_monitor() === dash._monitorIndex && ++ metaWindow.showing_on_its_workspace() && ++ metaWindow.get_window_type() != Meta.WindowType.DESKTOP; ++ }); ++ ++ /* Check if at least one window is near enough to the panel. ++ * If the dock is hidden, we need to account for the space it would take ++ * up when it slides out. This is avoid an ugly transition. ++ * */ ++ let factor = 0; ++ if (!this._settings.get_boolean('dock-fixed') && ++ this._dock.getDockState() == Dock.State.HIDDEN) ++ factor = 1; ++ let [leftCoord, topCoord] = this._actor.get_transformed_position(); ++ let threshold; ++ if (this._position === St.Side.LEFT) ++ threshold = leftCoord + this._actor.get_width() * (factor + 1); ++ else if (this._position === St.Side.RIGHT) ++ threshold = leftCoord - this._actor.get_width() * factor; ++ else if (this._position === St.Side.TOP) ++ threshold = topCoord + this._actor.get_height() * (factor + 1); ++ else ++ threshold = topCoord - this._actor.get_height() * factor; ++ ++ let scale = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ let isNearEnough = windows.some((metaWindow) => { ++ let coord; ++ if (this._position === St.Side.LEFT) { ++ coord = metaWindow.get_frame_rect().x; ++ return coord < threshold + 5 * scale; ++ } ++ else if (this._position === St.Side.RIGHT) { ++ coord = metaWindow.get_frame_rect().x + metaWindow.get_frame_rect().width; ++ return coord > threshold - 5 * scale; ++ } ++ else if (this._position === St.Side.TOP) { ++ coord = metaWindow.get_frame_rect().y; ++ return coord < threshold + 5 * scale; ++ } ++ else { ++ coord = metaWindow.get_frame_rect().y + metaWindow.get_frame_rect().height; ++ return coord > threshold - 5 * scale; ++ } ++ }); ++ ++ return isNearEnough; ++ } ++ ++ _updateStyles() { ++ this._getAlphas(); ++ ++ this._transparent_style = this._base_actor_style + ++ 'background-color: rgba(' + ++ this._backgroundColor + ', ' + this._transparentAlpha + ');' + ++ 'border-color: rgba(' + ++ this._backgroundColor + ', ' + this._transparentAlphaBorder + ');' + ++ 'transition-duration: ' + this._transparentTransition + 'ms;'; ++ ++ this._opaque_style = this._base_actor_style + ++ 'background-color: rgba(' + ++ this._backgroundColor + ', ' + this._opaqueAlpha + ');' + ++ 'border-color: rgba(' + ++ this._backgroundColor + ',' + this._opaqueAlphaBorder + ');' + ++ 'transition-duration: ' + this._opaqueTransition + 'ms;'; ++ ++ this.emit('styles-updated'); ++ } ++ ++ setColor(color) { ++ this._backgroundColor = color.red + ',' + color.green + ',' + color.blue; ++ this._updateStyles(); ++ } ++ ++ _getAlphas() { ++ // Create dummy object and add to the uiGroup to get it to the stage ++ let dummyObject = new St.Bin({ ++ name: 'dashtodockContainer', ++ }); ++ Main.uiGroup.add_child(dummyObject); ++ ++ dummyObject.add_style_class_name('dummy-opaque'); ++ let themeNode = dummyObject.get_theme_node(); ++ this._opaqueAlpha = themeNode.get_background_color().alpha / 255; ++ this._opaqueAlphaBorder = themeNode.get_border_color(0).alpha / 255; ++ this._opaqueTransition = themeNode.get_transition_duration(); ++ ++ dummyObject.add_style_class_name('dummy-transparent'); ++ themeNode = dummyObject.get_theme_node(); ++ this._transparentAlpha = themeNode.get_background_color().alpha / 255; ++ this._transparentAlphaBorder = themeNode.get_border_color(0).alpha / 255; ++ this._transparentTransition = themeNode.get_transition_duration(); ++ ++ Main.uiGroup.remove_child(dummyObject); ++ ++ if (this._settings.get_boolean('customize-alphas')) { ++ this._opaqueAlpha = this._settings.get_double('max-alpha'); ++ this._opaqueAlphaBorder = this._opaqueAlpha / 2; ++ this._transparentAlpha = this._settings.get_double('min-alpha'); ++ this._transparentAlphaBorder = this._transparentAlpha / 2; ++ } ++ } ++}; ++Signals.addSignalMethods(Transparency.prototype); +diff --git a/extensions/dash-to-dock/utils.js b/extensions/dash-to-dock/utils.js +new file mode 100644 +index 00000000..d315bd90 +--- /dev/null ++++ b/extensions/dash-to-dock/utils.js +@@ -0,0 +1,258 @@ ++const Clutter = imports.gi.Clutter; ++const Meta = imports.gi.Meta; ++const St = imports.gi.St; ++ ++/** ++ * Simplify global signals and function injections handling ++ * abstract class ++ */ ++const BasicHandler = class DashToDock_BasicHandler { ++ ++ constructor() { ++ this._storage = new Object(); ++ } ++ ++ add(/* unlimited 3-long array arguments */) { ++ // Convert arguments object to array, concatenate with generic ++ let args = Array.concat('generic', Array.slice(arguments)); ++ // Call addWithLabel with ags as if they were passed arguments ++ this.addWithLabel.apply(this, args); ++ } ++ ++ destroy() { ++ for( let label in this._storage ) ++ this.removeWithLabel(label); ++ } ++ ++ addWithLabel(label /* plus unlimited 3-long array arguments*/) { ++ if (this._storage[label] == undefined) ++ this._storage[label] = new Array(); ++ ++ // Skip first element of the arguments ++ for (let i = 1; i < arguments.length; i++) { ++ let item = this._storage[label]; ++ item.push(this._create(arguments[i])); ++ } ++ } ++ ++ removeWithLabel(label) { ++ if (this._storage[label]) { ++ for (let i = 0; i < this._storage[label].length; i++) ++ this._remove(this._storage[label][i]); ++ ++ delete this._storage[label]; ++ } ++ } ++ ++ // Virtual methods to be implemented by subclass ++ ++ /** ++ * Create single element to be stored in the storage structure ++ */ ++ _create(item) { ++ throw new Error('no implementation of _create in ' + this); ++ } ++ ++ /** ++ * Correctly delete single element ++ */ ++ _remove(item) { ++ throw new Error('no implementation of _remove in ' + this); ++ } ++}; ++ ++/** ++ * Manage global signals ++ */ ++var GlobalSignalsHandler = class DashToDock_GlobalSignalHandler extends BasicHandler { ++ ++ _create(item) { ++ let object = item[0]; ++ let event = item[1]; ++ let callback = item[2] ++ let id = object.connect(event, callback); ++ ++ return [object, id]; ++ } ++ ++ _remove(item) { ++ item[0].disconnect(item[1]); ++ } ++}; ++ ++/** ++ * Color manipulation utilities ++ */ ++var ColorUtils = class DashToDock_ColorUtils { ++ ++ // Darken or brigthen color by a fraction dlum ++ // Each rgb value is modified by the same fraction. ++ // Return "#rrggbb" string ++ static ColorLuminance(r, g, b, dlum) { ++ let rgbString = '#'; ++ ++ rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(r*(1+dlum), 0), 255)), 2); ++ rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(g*(1+dlum), 0), 255)), 2); ++ rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(b*(1+dlum), 0), 255)), 2); ++ ++ return rgbString; ++ } ++ ++ // Convert decimal to an hexadecimal string adding the desired padding ++ static _decimalToHex(d, padding) { ++ let hex = d.toString(16); ++ while (hex.length < padding) ++ hex = '0'+ hex; ++ return hex; ++ } ++ ++ // Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]). ++ // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV ++ // here with h = [0,1] instead of [0, 360] ++ // Accept either (h,s,v) independently or {h:h, s:s, v:v} object. ++ // Return {r:r, g:g, b:b} object. ++ static HSVtoRGB(h, s, v) { ++ if (arguments.length === 1) { ++ s = h.s; ++ v = h.v; ++ h = h.h; ++ } ++ ++ let r,g,b; ++ let c = v*s; ++ let h1 = h*6; ++ let x = c*(1 - Math.abs(h1 % 2 - 1)); ++ let m = v - c; ++ ++ if (h1 <=1) ++ r = c + m, g = x + m, b = m; ++ else if (h1 <=2) ++ r = x + m, g = c + m, b = m; ++ else if (h1 <=3) ++ r = m, g = c + m, b = x + m; ++ else if (h1 <=4) ++ r = m, g = x + m, b = c + m; ++ else if (h1 <=5) ++ r = x + m, g = m, b = c + m; ++ else ++ r = c + m, g = m, b = x + m; ++ ++ return { ++ r: Math.round(r * 255), ++ g: Math.round(g * 255), ++ b: Math.round(b * 255) ++ }; ++ } ++ ++ // Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]). ++ // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV ++ // here with h = [0,1] instead of [0, 360] ++ // Accept either (r,g,b) independently or {r:r, g:g, b:b} object. ++ // Return {h:h, s:s, v:v} object. ++ static RGBtoHSV(r, g, b) { ++ if (arguments.length === 1) { ++ r = r.r; ++ g = r.g; ++ b = r.b; ++ } ++ ++ let h,s,v; ++ ++ let M = Math.max(r, g, b); ++ let m = Math.min(r, g, b); ++ let c = M - m; ++ ++ if (c == 0) ++ h = 0; ++ else if (M == r) ++ h = ((g-b)/c) % 6; ++ else if (M == g) ++ h = (b-r)/c + 2; ++ else ++ h = (r-g)/c + 4; ++ ++ h = h/6; ++ v = M/255; ++ if (M !== 0) ++ s = c/M; ++ else ++ s = 0; ++ ++ return { ++ h: h, ++ s: s, ++ v: v ++ }; ++ } ++}; ++ ++/** ++ * Manage function injection: both instances and prototype can be overridden ++ * and restored ++ */ ++var InjectionsHandler = class DashToDock_InjectionsHandler extends BasicHandler { ++ ++ _create(item) { ++ let object = item[0]; ++ let name = item[1]; ++ let injectedFunction = item[2]; ++ let original = object[name]; ++ ++ object[name] = injectedFunction; ++ return [object, name, injectedFunction, original]; ++ } ++ ++ _remove(item) { ++ let object = item[0]; ++ let name = item[1]; ++ let original = item[3]; ++ object[name] = original; ++ } ++}; ++ ++/** ++ * Return the actual position reverseing left and right in rtl ++ */ ++function getPosition(settings) { ++ let position = settings.get_enum('dock-position'); ++ if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) { ++ if (position == St.Side.LEFT) ++ position = St.Side.RIGHT; ++ else if (position == St.Side.RIGHT) ++ position = St.Side.LEFT; ++ } ++ return position; ++} ++ ++function drawRoundedLine(cr, x, y, width, height, isRoundLeft, isRoundRight, stroke, fill) { ++ if (height > width) { ++ y += Math.floor((height - width) / 2.0); ++ height = width; ++ } ++ ++ height = 2.0 * Math.floor(height / 2.0); ++ ++ var leftRadius = isRoundLeft ? height / 2.0 : 0.0; ++ var rightRadius = isRoundRight ? height / 2.0 : 0.0; ++ ++ cr.moveTo(x + width - rightRadius, y); ++ cr.lineTo(x + leftRadius, y); ++ if (isRoundLeft) ++ cr.arcNegative(x + leftRadius, y + leftRadius, leftRadius, -Math.PI/2, Math.PI/2); ++ else ++ cr.lineTo(x, y + height); ++ cr.lineTo(x + width - rightRadius, y + height); ++ if (isRoundRight) ++ cr.arcNegative(x + width - rightRadius, y + rightRadius, rightRadius, Math.PI/2, -Math.PI/2); ++ else ++ cr.lineTo(x + width, y); ++ cr.closePath(); ++ ++ if (fill != null) { ++ cr.setSource(fill); ++ cr.fillPreserve(); ++ } ++ if (stroke != null) ++ cr.setSource(stroke); ++ cr.stroke(); ++} +diff --git a/extensions/dash-to-dock/windowPreview.js b/extensions/dash-to-dock/windowPreview.js +new file mode 100644 +index 00000000..ea98f27e +--- /dev/null ++++ b/extensions/dash-to-dock/windowPreview.js +@@ -0,0 +1,578 @@ ++/* ++ * Credits: ++ * This file is based on code from the Dash to Panel extension by Jason DeRose ++ * and code from the Taskbar extension by Zorin OS ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++const Clutter = imports.gi.Clutter; ++const GLib = imports.gi.GLib; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++const Main = imports.ui.main; ++const Gtk = imports.gi.Gtk; ++ ++const Params = imports.misc.params; ++const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++ ++const PREVIEW_MAX_WIDTH = 250; ++const PREVIEW_MAX_HEIGHT = 150; ++ ++var WindowPreviewMenu = class DashToDock_WindowPreviewMenu extends PopupMenu.PopupMenu { ++ ++ constructor(source, settings) { ++ let side = Utils.getPosition(settings); ++ super(source.actor, 0.5, side); ++ ++ this._dtdSettings = settings; ++ ++ // We want to keep the item hovered while the menu is up ++ this.blockSourceEvents = true; ++ ++ this._source = source; ++ this._app = this._source.app; ++ let monitorIndex = this._source.monitorIndex; ++ ++ this.actor.add_style_class_name('app-well-menu'); ++ this.actor.set_style('max-width: ' + (Main.layoutManager.monitors[monitorIndex].width - 22) + 'px; ' + ++ 'max-height: ' + (Main.layoutManager.monitors[monitorIndex].height - 22) + 'px;'); ++ this.actor.hide(); ++ ++ // Chain our visibility and lifecycle to that of the source ++ this._mappedId = this._source.actor.connect('notify::mapped', () => { ++ if (!this._source.actor.mapped) ++ this.close(); ++ }); ++ this._destroyId = this._source.actor.connect('destroy', this.destroy.bind(this)); ++ ++ Main.uiGroup.add_actor(this.actor); ++ ++ // Change the initialized side where required. ++ this._arrowSide = side; ++ this._boxPointer._arrowSide = side; ++ this._boxPointer._userArrowSide = side; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ } ++ ++ _redisplay() { ++ if (this._previewBox) ++ this._previewBox.destroy(); ++ this._previewBox = new WindowPreviewList(this._source, this._dtdSettings); ++ this.addMenuItem(this._previewBox); ++ this._previewBox._redisplay(); ++ } ++ ++ popup() { ++ let windows = this._source.getInterestingWindows(); ++ if (windows.length > 0) { ++ this._redisplay(); ++ this.open(); ++ this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); ++ this._source.emit('sync-tooltip'); ++ } ++ } ++ ++ _onDestroy() { ++ if (this._mappedId) ++ this._source.actor.disconnect(this._mappedId); ++ ++ if (this._destroyId) ++ this._source.actor.disconnect(this._destroyId); ++ } ++}; ++ ++var WindowPreviewList = class DashToDock_WindowPreviewList extends PopupMenu.PopupMenuSection { ++ ++ constructor(source, settings) { ++ super(); ++ this._dtdSettings = settings; ++ ++ this.actor = new St.ScrollView({ name: 'dashtodockWindowScrollview', ++ hscrollbar_policy: Gtk.PolicyType.NEVER, ++ vscrollbar_policy: Gtk.PolicyType.NEVER, ++ enable_mouse_scrolling: true }); ++ ++ this.actor.connect('scroll-event', this._onScrollEvent.bind(this)); ++ ++ let position = Utils.getPosition(this._dtdSettings); ++ this.isHorizontal = position == St.Side.BOTTOM || position == St.Side.TOP; ++ this.box.set_vertical(!this.isHorizontal); ++ this.box.set_name('dashtodockWindowList'); ++ this.actor.add_actor(this.box); ++ this.actor._delegate = this; ++ ++ this._shownInitially = false; ++ ++ this._source = source; ++ this.app = source.app; ++ ++ this._redisplayId = Main.initializeDeferredWork(this.actor, this._redisplay.bind(this)); ++ ++ this.actor.connect('destroy', this._onDestroy.bind(this)); ++ this._stateChangedId = this.app.connect('windows-changed', ++ this._queueRedisplay.bind(this)); ++ } ++ ++ _queueRedisplay () { ++ Main.queueDeferredWork(this._redisplayId); ++ } ++ ++ _onScrollEvent(actor, event) { ++ // Event coordinates are relative to the stage but can be transformed ++ // as the actor will only receive events within his bounds. ++ let stage_x, stage_y, ok, event_x, event_y, actor_w, actor_h; ++ [stage_x, stage_y] = event.get_coords(); ++ [ok, event_x, event_y] = actor.transform_stage_point(stage_x, stage_y); ++ [actor_w, actor_h] = actor.get_size(); ++ ++ // If the scroll event is within a 1px margin from ++ // the relevant edge of the actor, let the event propagate. ++ if (event_y >= actor_h - 2) ++ return Clutter.EVENT_PROPAGATE; ++ ++ // Skip to avoid double events mouse ++ if (event.is_pointer_emulated()) ++ return Clutter.EVENT_STOP; ++ ++ let adjustment, delta; ++ ++ if (this.isHorizontal) ++ adjustment = this.actor.get_hscroll_bar().get_adjustment(); ++ else ++ adjustment = this.actor.get_vscroll_bar().get_adjustment(); ++ ++ let increment = adjustment.step_increment; ++ ++ switch ( event.get_scroll_direction() ) { ++ case Clutter.ScrollDirection.UP: ++ delta = -increment; ++ break; ++ case Clutter.ScrollDirection.DOWN: ++ delta = +increment; ++ break; ++ case Clutter.ScrollDirection.SMOOTH: ++ let [dx, dy] = event.get_scroll_delta(); ++ delta = dy*increment; ++ delta += dx*increment; ++ break; ++ ++ } ++ ++ adjustment.set_value(adjustment.get_value() + delta); ++ ++ return Clutter.EVENT_STOP; ++ } ++ ++ _onDestroy() { ++ this.app.disconnect(this._stateChangedId); ++ this._stateChangedId = 0; ++ } ++ ++ _createPreviewItem(window) { ++ let preview = new WindowPreviewMenuItem(window); ++ return preview; ++ } ++ ++ _redisplay () { ++ let children = this._getMenuItems().filter(function(actor) { ++ return actor._window; ++ }); ++ ++ // Windows currently on the menu ++ let oldWin = children.map(function(actor) { ++ return actor._window; ++ }); ++ ++ // All app windows with a static order ++ let newWin = this._source.getInterestingWindows().sort(function(a, b) { ++ return a.get_stable_sequence() > b.get_stable_sequence(); ++ }); ++ ++ let addedItems = []; ++ let removedActors = []; ++ ++ let newIndex = 0; ++ let oldIndex = 0; ++ ++ while (newIndex < newWin.length || oldIndex < oldWin.length) { ++ // No change at oldIndex/newIndex ++ if (oldWin[oldIndex] && ++ oldWin[oldIndex] == newWin[newIndex]) { ++ oldIndex++; ++ newIndex++; ++ continue; ++ } ++ ++ // Window removed at oldIndex ++ if (oldWin[oldIndex] && ++ newWin.indexOf(oldWin[oldIndex]) == -1) { ++ removedActors.push(children[oldIndex]); ++ oldIndex++; ++ continue; ++ } ++ ++ // Window added at newIndex ++ if (newWin[newIndex] && ++ oldWin.indexOf(newWin[newIndex]) == -1) { ++ addedItems.push({ item: this._createPreviewItem(newWin[newIndex]), ++ pos: newIndex }); ++ newIndex++; ++ continue; ++ } ++ ++ // Window moved ++ let insertHere = newWin[newIndex + 1] && ++ newWin[newIndex + 1] == oldWin[oldIndex]; ++ let alreadyRemoved = removedActors.reduce(function(result, actor) { ++ let removedWin = actor._window; ++ return result || removedWin == newWin[newIndex]; ++ }, false); ++ ++ if (insertHere || alreadyRemoved) { ++ addedItems.push({ item: this._createPreviewItem(newWin[newIndex]), ++ pos: newIndex + removedActors.length }); ++ newIndex++; ++ } else { ++ removedActors.push(children[oldIndex]); ++ oldIndex++; ++ } ++ } ++ ++ for (let i = 0; i < addedItems.length; i++) ++ this.addMenuItem(addedItems[i].item, ++ addedItems[i].pos); ++ ++ for (let i = 0; i < removedActors.length; i++) { ++ let item = removedActors[i]; ++ if (this._shownInitially) ++ item._animateOutAndDestroy(); ++ else ++ item.actor.destroy(); ++ } ++ ++ // Skip animations on first run when adding the initial set ++ // of items, to avoid all items zooming in at once ++ let animate = this._shownInitially; ++ ++ if (!this._shownInitially) ++ this._shownInitially = true; ++ ++ for (let i = 0; i < addedItems.length; i++) ++ addedItems[i].item.show(animate); ++ ++ // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 ++ // Without it, StBoxLayout may use a stale size cache ++ this.box.queue_relayout(); ++ ++ if (newWin.length < 1) ++ this._getTopMenu().close(~0); ++ ++ // As for upstream: ++ // St.ScrollView always requests space horizontally for a possible vertical ++ // scrollbar if in AUTOMATIC mode. Doing better would require implementation ++ // of width-for-height in St.BoxLayout and St.ScrollView. This looks bad ++ // when we *don't* need it, so turn off the scrollbar when that's true. ++ // Dynamic changes in whether we need it aren't handled properly. ++ let needsScrollbar = this._needsScrollbar(); ++ let scrollbar_policy = needsScrollbar ? Gtk.PolicyType.AUTOMATIC : Gtk.PolicyType.NEVER; ++ if (this.isHorizontal) ++ this.actor.hscrollbar_policy = scrollbar_policy; ++ else ++ this.actor.vscrollbar_policy = scrollbar_policy; ++ ++ if (needsScrollbar) ++ this.actor.add_style_pseudo_class('scrolled'); ++ else ++ this.actor.remove_style_pseudo_class('scrolled'); ++ } ++ ++ _needsScrollbar() { ++ let topMenu = this._getTopMenu(); ++ let topThemeNode = topMenu.actor.get_theme_node(); ++ if (this.isHorizontal) { ++ let [topMinWidth, topNaturalWidth] = topMenu.actor.get_preferred_width(-1); ++ let topMaxWidth = topThemeNode.get_max_width(); ++ return topMaxWidth >= 0 && topNaturalWidth >= topMaxWidth; ++ } else { ++ let [topMinHeight, topNaturalHeight] = topMenu.actor.get_preferred_height(-1); ++ let topMaxHeight = topThemeNode.get_max_height(); ++ return topMaxHeight >= 0 && topNaturalHeight >= topMaxHeight; ++ } ++ ++ } ++ ++ isAnimatingOut() { ++ return this.actor.get_children().reduce(function(result, actor) { ++ return result || actor.animatingOut; ++ }, false); ++ } ++}; ++ ++var WindowPreviewMenuItem = class DashToDock_WindowPreviewMenuItem extends PopupMenu.PopupBaseMenuItem { ++ ++ constructor(window, params) { ++ super(params); ++ ++ this._window = window; ++ this._destroyId = 0; ++ this._windowAddedId = 0; ++ ++ // We don't want this: it adds spacing on the left of the item. ++ this.actor.remove_child(this._ornamentLabel); ++ this.actor.add_style_class_name('dashtodock-app-well-preview-menu-item'); ++ ++ this._cloneBin = new St.Bin(); ++ this._cloneBin.set_size(PREVIEW_MAX_WIDTH, PREVIEW_MAX_HEIGHT); ++ ++ // TODO: improve the way the closebutton is layout. Just use some padding ++ // for the moment. ++ this._cloneBin.set_style('padding-bottom: 0.5em'); ++ ++ this.closeButton = new St.Button({ style_class: 'window-close', ++ x_expand: true, ++ y_expand: true}); ++ this.closeButton.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' })); ++ this.closeButton.set_x_align(Clutter.ActorAlign.END); ++ this.closeButton.set_y_align(Clutter.ActorAlign.START); ++ ++ ++ this.closeButton.opacity = 0; ++ this.closeButton.connect('clicked', this._closeWindow.bind(this)); ++ ++ let overlayGroup = new Clutter.Actor({layout_manager: new Clutter.BinLayout() }); ++ ++ overlayGroup.add_actor(this._cloneBin); ++ overlayGroup.add_actor(this.closeButton); ++ ++ let label = new St.Label({ text: window.get_title()}); ++ label.set_style('max-width: '+PREVIEW_MAX_WIDTH +'px'); ++ let labelBin = new St.Bin({ child: label, ++ x_align: St.Align.MIDDLE}); ++ ++ this._windowTitleId = this._window.connect('notify::title', () => { ++ label.set_text(this._window.get_title()); ++ }); ++ ++ let box = new St.BoxLayout({ vertical: true, ++ reactive:true, ++ x_expand:true }); ++ box.add(overlayGroup); ++ box.add(labelBin); ++ this.actor.add_actor(box); ++ ++ this.actor.connect('enter-event', ++ this._onEnter.bind(this)); ++ this.actor.connect('leave-event', ++ this._onLeave.bind(this)); ++ this.actor.connect('key-focus-in', ++ this._onEnter.bind(this)); ++ this.actor.connect('key-focus-out', ++ this._onLeave.bind(this)); ++ ++ this._cloneTexture(window); ++ ++ } ++ ++ _cloneTexture(metaWin){ ++ ++ let mutterWindow = metaWin.get_compositor_private(); ++ ++ // Newly-created windows are added to a workspace before ++ // the compositor finds out about them... ++ // Moreover sometimes they return an empty texture, thus as a workarounf also check for it size ++ if (!mutterWindow || !mutterWindow.get_texture() || !mutterWindow.get_texture().get_size()[0]) { ++ let id = Mainloop.idle_add(() => { ++ // Check if there's still a point in getting the texture, ++ // otherwise this could go on indefinitely ++ if (this.actor && metaWin.get_workspace()) ++ this._cloneTexture(metaWin); ++ return GLib.SOURCE_REMOVE; ++ }); ++ GLib.Source.set_name_by_id(id, '[dash-to-dock] this._cloneTexture'); ++ return; ++ } ++ ++ let windowTexture = mutterWindow.get_texture(); ++ let [width, height] = windowTexture.get_size(); ++ ++ let scale = Math.min(1.0, PREVIEW_MAX_WIDTH/width, PREVIEW_MAX_HEIGHT/height); ++ ++ let clone = new Clutter.Clone ({ source: windowTexture, ++ reactive: true, ++ width: width * scale, ++ height: height * scale }); ++ ++ // when the source actor is destroyed, i.e. the window closed, first destroy the clone ++ // and then destroy the menu item (do this animating out) ++ this._destroyId = mutterWindow.connect('destroy', () => { ++ clone.destroy(); ++ this._destroyId = 0; // avoid to try to disconnect this signal from mutterWindow in _onDestroy(), ++ // as the object was just destroyed ++ this._animateOutAndDestroy(); ++ }); ++ ++ this._clone = clone; ++ this._mutterWindow = mutterWindow; ++ this._cloneBin.set_child(this._clone); ++ } ++ ++ _windowCanClose() { ++ return this._window.can_close() && ++ !this._hasAttachedDialogs(); ++ } ++ ++ _closeWindow(actor) { ++ this._workspace = this._window.get_workspace(); ++ ++ // This mechanism is copied from the workspace.js upstream code ++ // It forces window activation if the windows don't get closed, ++ // for instance because asking user confirmation, by monitoring the opening of ++ // such additional confirmation window ++ this._windowAddedId = this._workspace.connect('window-added', ++ this._onWindowAdded.bind(this)); ++ ++ this.deleteAllWindows(); ++ } ++ ++ deleteAllWindows() { ++ // Delete all windows, starting from the bottom-most (most-modal) one ++ //let windows = this._window.get_compositor_private().get_children(); ++ let windows = this._clone.get_children(); ++ for (let i = windows.length - 1; i >= 1; i--) { ++ let realWindow = windows[i].source; ++ let metaWindow = realWindow.meta_window; ++ ++ metaWindow.delete(global.get_current_time()); ++ } ++ ++ this._window.delete(global.get_current_time()); ++ } ++ ++ _onWindowAdded(workspace, win) { ++ let metaWindow = this._window; ++ ++ if (win.get_transient_for() == metaWindow) { ++ workspace.disconnect(this._windowAddedId); ++ this._windowAddedId = 0; ++ ++ // use an idle handler to avoid mapping problems - ++ // see comment in Workspace._windowAdded ++ let id = Mainloop.idle_add(() => { ++ this.emit('activate'); ++ return GLib.SOURCE_REMOVE; ++ }); ++ GLib.Source.set_name_by_id(id, '[dash-to-dock] this.emit'); ++ } ++ } ++ ++ _hasAttachedDialogs() { ++ // count trasient windows ++ let n=0; ++ this._window.foreach_transient(function(){n++;}); ++ return n>0; ++ } ++ ++ _onEnter() { ++ this._showCloseButton(); ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _onLeave() { ++ if (!this._cloneBin.has_pointer && ++ !this.closeButton.has_pointer) ++ this._hideCloseButton(); ++ ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _idleToggleCloseButton() { ++ this._idleToggleCloseId = 0; ++ ++ if (!this._cloneBin.has_pointer && ++ !this.closeButton.has_pointer) ++ this._hideCloseButton(); ++ ++ return GLib.SOURCE_REMOVE; ++ } ++ ++ _showCloseButton() { ++ ++ if (this._windowCanClose()) { ++ this.closeButton.show(); ++ Tweener.addTween(this.closeButton, ++ { opacity: 255, ++ time: Workspace.CLOSE_BUTTON_FADE_TIME, ++ transition: 'easeOutQuad' }); ++ } ++ } ++ ++ _hideCloseButton() { ++ Tweener.addTween(this.closeButton, ++ { opacity: 0, ++ time: Workspace.CLOSE_BUTTON_FADE_TIME, ++ transition: 'easeInQuad' }); ++ } ++ ++ show(animate) { ++ let fullWidth = this.actor.get_width(); ++ ++ this.actor.opacity = 0; ++ this.actor.set_width(0); ++ ++ let time = animate ? 0.25 : 0; ++ Tweener.addTween(this.actor, ++ { opacity: 255, ++ width: fullWidth, ++ time: time, ++ transition: 'easeInOutQuad' ++ }); ++ } ++ ++ _animateOutAndDestroy() { ++ Tweener.addTween(this.actor, ++ { opacity: 0, ++ time: 0.25, ++ }); ++ ++ Tweener.addTween(this.actor, ++ { height: 0, ++ width: 0, ++ time: 0.25, ++ delay: 0.25, ++ onCompleteScope: this, ++ onComplete() { ++ this.actor.destroy(); ++ } ++ }); ++ } ++ ++ activate() { ++ this._getTopMenu().close(); ++ Main.activateWindow(this._window); ++ } ++ ++ _onDestroy() { ++ super._onDestroy(); ++ ++ if (this._windowAddedId > 0) { ++ this._workspace.disconnect(this._windowAddedId); ++ this._windowAddedId = 0; ++ } ++ ++ if (this._destroyId > 0) { ++ this._mutterWindow.disconnect(this._destroyId); ++ this._destroyId = 0; ++ } ++ ++ if (this._windowTitleId > 0) { ++ this._window.disconnect(this._windowTitleId); ++ this._windowTitleId = 0; ++ } ++ } ++}; ++ +diff --git a/meson.build b/meson.build +index 6050c32f..2909135a 100644 +--- a/meson.build ++++ b/meson.build +@@ -49,6 +49,7 @@ default_extensions += [ + all_extensions = default_extensions + all_extensions += [ + 'auto-move-windows', ++ 'dash-to-dock', + 'native-window-placement', + 'top-icons', + 'user-theme' +-- +2.38.1 + + +From 9ffe67c4d25f34fa6c3af5ee4ddbd0be3018ef14 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 20 May 2015 18:55:47 +0200 +Subject: [PATCH 03/11] Add panel-favorites extension + +--- + extensions/panel-favorites/extension.js | 267 ++++++++++++++++++++ + extensions/panel-favorites/meson.build | 5 + + extensions/panel-favorites/metadata.json.in | 10 + + extensions/panel-favorites/stylesheet.css | 14 + + meson.build | 1 + + 5 files changed, 297 insertions(+) + create mode 100644 extensions/panel-favorites/extension.js + create mode 100644 extensions/panel-favorites/meson.build + create mode 100644 extensions/panel-favorites/metadata.json.in + create mode 100644 extensions/panel-favorites/stylesheet.css + +diff --git a/extensions/panel-favorites/extension.js b/extensions/panel-favorites/extension.js +new file mode 100644 +index 00000000..b817dbb6 +--- /dev/null ++++ b/extensions/panel-favorites/extension.js +@@ -0,0 +1,267 @@ ++// Copyright (C) 2011-2013 R M Yorston ++// Licence: GPLv2+ ++ ++const Clutter = imports.gi.Clutter; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Lang = imports.lang; ++const Shell = imports.gi.Shell; ++const Signals = imports.signals; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++ ++const AppFavorites = imports.ui.appFavorites; ++const Main = imports.ui.main; ++const Panel = imports.ui.panel; ++const Tweener = imports.ui.tweener; ++ ++const PANEL_LAUNCHER_LABEL_SHOW_TIME = 0.15; ++const PANEL_LAUNCHER_LABEL_HIDE_TIME = 0.1; ++const PANEL_LAUNCHER_HOVER_TIMEOUT = 300; ++ ++const PanelLauncher = new Lang.Class({ ++ Name: 'PanelLauncher', ++ ++ _init: function(app) { ++ this.actor = new St.Button({ style_class: 'panel-button', ++ reactive: true }); ++ this.iconSize = 24; ++ let icon = app.create_icon_texture(this.iconSize); ++ this.actor.set_child(icon); ++ this.actor._delegate = this; ++ let text = app.get_name(); ++ if ( app.get_description() ) { ++ text += '\n' + app.get_description(); ++ } ++ ++ this.label = new St.Label({ style_class: 'panel-launcher-label'}); ++ this.label.set_text(text); ++ Main.layoutManager.addChrome(this.label); ++ this.label.hide(); ++ this.actor.label_actor = this.label; ++ ++ this._app = app; ++ this.actor.connect('clicked', Lang.bind(this, function() { ++ this._app.open_new_window(-1); ++ })); ++ this.actor.connect('notify::hover', ++ Lang.bind(this, this._onHoverChanged)); ++ this.actor.opacity = 207; ++ ++ this.actor.connect('notify::allocation', Lang.bind(this, this._alloc)); ++ }, ++ ++ _onHoverChanged: function(actor) { ++ actor.opacity = actor.hover ? 255 : 207; ++ }, ++ ++ _alloc: function() { ++ let size = this.actor.allocation.y2 - this.actor.allocation.y1 - 3; ++ if ( size >= 24 && size != this.iconSize ) { ++ this.actor.get_child().destroy(); ++ this.iconSize = size; ++ let icon = this._app.create_icon_texture(this.iconSize); ++ this.actor.set_child(icon); ++ } ++ }, ++ ++ showLabel: function() { ++ this.label.opacity = 0; ++ this.label.show(); ++ ++ let [stageX, stageY] = this.actor.get_transformed_position(); ++ ++ let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1; ++ let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1; ++ let labelWidth = this.label.get_width(); ++ ++ let node = this.label.get_theme_node(); ++ let yOffset = node.get_length('-y-offset'); ++ ++ let y = stageY + itemHeight + yOffset; ++ let x = Math.floor(stageX + itemWidth/2 - labelWidth/2); ++ ++ let parent = this.label.get_parent(); ++ let parentWidth = parent.allocation.x2 - parent.allocation.x1; ++ ++ if ( Clutter.get_default_text_direction() == Clutter.TextDirection.LTR ) { ++ // stop long tooltips falling off the right of the screen ++ x = Math.min(x, parentWidth-labelWidth-6); ++ // but whatever happens don't let them fall of the left ++ x = Math.max(x, 6); ++ } ++ else { ++ x = Math.max(x, 6); ++ x = Math.min(x, parentWidth-labelWidth-6); ++ } ++ ++ this.label.set_position(x, y); ++ Tweener.addTween(this.label, ++ { opacity: 255, ++ time: PANEL_LAUNCHER_LABEL_SHOW_TIME, ++ transition: 'easeOutQuad', ++ }); ++ }, ++ ++ hideLabel: function() { ++ this.label.opacity = 255; ++ Tweener.addTween(this.label, ++ { opacity: 0, ++ time: PANEL_LAUNCHER_LABEL_HIDE_TIME, ++ transition: 'easeOutQuad', ++ onComplete: Lang.bind(this, function() { ++ this.label.hide(); ++ }) ++ }); ++ }, ++ ++ destroy: function() { ++ this.label.destroy(); ++ this.actor.destroy(); ++ } ++}); ++ ++const PanelFavorites = new Lang.Class({ ++ Name: 'PanelFavorites', ++ ++ _init: function() { ++ this._showLabelTimeoutId = 0; ++ this._resetHoverTimeoutId = 0; ++ this._labelShowing = false; ++ ++ this.actor = new St.BoxLayout({ name: 'panelFavorites', ++ x_expand: true, y_expand: true, ++ style_class: 'panel-favorites' }); ++ this._display(); ++ ++ this.container = new St.Bin({ y_fill: true, ++ x_fill: true, ++ child: this.actor }); ++ ++ this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); ++ this._installChangedId = Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, this._redisplay)); ++ this._changedId = AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._redisplay)); ++ }, ++ ++ _redisplay: function() { ++ for ( let i=0; i 0) { ++ Mainloop.source_remove(this._resetHoverTimeoutId); ++ this._resetHoverTimeoutId = 0; ++ } ++ } ++ } else { ++ if (this._showLabelTimeoutId > 0) { ++ Mainloop.source_remove(this._showLabelTimeoutId); ++ this._showLabelTimeoutId = 0; ++ } ++ launcher.hideLabel(); ++ if (this._labelShowing) { ++ this._resetHoverTimeoutId = Mainloop.timeout_add( ++ PANEL_LAUNCHER_HOVER_TIMEOUT, ++ Lang.bind(this, function() { ++ this._labelShowing = false; ++ this._resetHoverTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ } ++ } ++ }, ++ ++ _onDestroy: function() { ++ if ( this._installChangedId != 0 ) { ++ Shell.AppSystem.get_default().disconnect(this._installChangedId); ++ this._installChangedId = 0; ++ } ++ ++ if ( this._changedId != 0 ) { ++ AppFavorites.getAppFavorites().disconnect(this._changedId); ++ this._changedId = 0; ++ } ++ } ++}); ++Signals.addSignalMethods(PanelFavorites.prototype); ++ ++let myAddToStatusArea; ++let panelFavorites; ++ ++function enable() { ++ Panel.Panel.prototype.myAddToStatusArea = myAddToStatusArea; ++ ++ // place panel to left of app menu, or failing that at right end of box ++ let siblings = Main.panel._leftBox.get_children(); ++ let appMenu = Main.panel.statusArea['appMenu']; ++ let pos = appMenu ? siblings.indexOf(appMenu.container) : siblings.length; ++ ++ panelFavorites = new PanelFavorites(); ++ Main.panel.myAddToStatusArea('panel-favorites', panelFavorites, ++ pos, 'left'); ++} ++ ++function disable() { ++ delete Panel.Panel.prototype.myAddToStatusArea; ++ ++ panelFavorites.actor.destroy(); ++ panelFavorites.emit('destroy'); ++ panelFavorites = null; ++} ++ ++function init() { ++ myAddToStatusArea = function(role, indicator, position, box) { ++ if (this.statusArea[role]) ++ throw new Error('Extension point conflict: there is already a status indicator for role ' + role); ++ ++ position = position || 0; ++ let boxes = { ++ left: this._leftBox, ++ center: this._centerBox, ++ right: this._rightBox ++ }; ++ let boxContainer = boxes[box] || this._rightBox; ++ this.statusArea[role] = indicator; ++ this._addToPanelBox(role, indicator, position, boxContainer); ++ return indicator; ++ }; ++} +diff --git a/extensions/panel-favorites/meson.build b/extensions/panel-favorites/meson.build +new file mode 100644 +index 00000000..48504f63 +--- /dev/null ++++ b/extensions/panel-favorites/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/panel-favorites/metadata.json.in b/extensions/panel-favorites/metadata.json.in +new file mode 100644 +index 00000000..037f2813 +--- /dev/null ++++ b/extensions/panel-favorites/metadata.json.in +@@ -0,0 +1,10 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Frippery Panel Favorites", ++"description": "Add launchers for Favorites to the panel", ++"shell-version": [ "@shell_current@" ], ++"url": "http://intgat.tigress.co.uk/rmy/extensions/index.html" ++} +diff --git a/extensions/panel-favorites/stylesheet.css b/extensions/panel-favorites/stylesheet.css +new file mode 100644 +index 00000000..120adacb +--- /dev/null ++++ b/extensions/panel-favorites/stylesheet.css +@@ -0,0 +1,14 @@ ++.panel-favorites { ++ spacing: 6px; ++} ++ ++.panel-launcher-label { ++ border-radius: 7px; ++ padding: 4px 12px; ++ background-color: rgba(0,0,0,0.9); ++ color: white; ++ text-align: center; ++ font-size: 9pt; ++ font-weight: bold; ++ -y-offset: 6px; ++} +diff --git a/meson.build b/meson.build +index 2909135a..e8e00dce 100644 +--- a/meson.build ++++ b/meson.build +@@ -51,6 +51,7 @@ all_extensions += [ + 'auto-move-windows', + 'dash-to-dock', + 'native-window-placement', ++ 'panel-favorites', + 'top-icons', + 'user-theme' + ] +-- +2.38.1 + + +From 4bd1716e559af83795eec5b02025798b02c09fa4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 4 Mar 2016 17:07:21 +0100 +Subject: [PATCH 04/11] Add updates-dialog extension + +--- + extensions/updates-dialog/extension.js | 503 ++++++++++++++++++ + extensions/updates-dialog/meson.build | 7 + + extensions/updates-dialog/metadata.json.in | 10 + + ...hell.extensions.updates-dialog.gschema.xml | 30 ++ + extensions/updates-dialog/stylesheet.css | 1 + + meson.build | 1 + + po/POTFILES.in | 2 + + 7 files changed, 554 insertions(+) + create mode 100644 extensions/updates-dialog/extension.js + create mode 100644 extensions/updates-dialog/meson.build + create mode 100644 extensions/updates-dialog/metadata.json.in + create mode 100644 extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml + create mode 100644 extensions/updates-dialog/stylesheet.css + +diff --git a/extensions/updates-dialog/extension.js b/extensions/updates-dialog/extension.js +new file mode 100644 +index 00000000..59f6dcfe +--- /dev/null ++++ b/extensions/updates-dialog/extension.js +@@ -0,0 +1,503 @@ ++/* ++ * Copyright (c) 2015 Red Hat, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++/* exported enable disable */ ++ ++const { Clutter, Gio, GLib, PackageKitGlib: PkgKit, Pango, Polkit, St } = imports.gi; ++const Signals = imports.signals; ++ ++const EndSessionDialog = imports.ui.endSessionDialog; ++const ModalDialog = imports.ui.modalDialog; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++ ++const PkIface = ' \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++'; ++ ++const PkOfflineIface = ' \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++'; ++ ++const PkTransactionIface = ' \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++'; ++ ++const LoginManagerIface = ' \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++ \ ++'; ++ ++const PkProxy = Gio.DBusProxy.makeProxyWrapper(PkIface); ++const PkOfflineProxy = Gio.DBusProxy.makeProxyWrapper(PkOfflineIface); ++const PkTransactionProxy = Gio.DBusProxy.makeProxyWrapper(PkTransactionIface); ++const LoginManagerProxy = Gio.DBusProxy.makeProxyWrapper(LoginManagerIface); ++ ++let pkProxy = null; ++let pkOfflineProxy = null; ++let loginManagerProxy = null; ++let updatesDialog = null; ++let extensionSettings = null; ++let cancellable = null; ++ ++let updatesCheckInProgress = false; ++let updatesCheckRequested = false; ++let securityUpdates = []; ++ ++function getDetailText(period) { ++ let text = _('Important security updates need to be installed.\n'); ++ if (period < 60) { ++ text += ngettext( ++ 'You can close this dialog and get %d minute to finish your work.', ++ 'You can close this dialog and get %d minutes to finish your work.', ++ period) ++ .format(period); ++ } else { ++ text += ngettext( ++ 'You can close this dialog and get %d hour to finish your work.', ++ 'You can close this dialog and get %d hours to finish your work.', ++ Math.floor(period / 60)) ++ .format(Math.floor(period / 60)); ++ } ++ return text; ++} ++ ++const UpdatesDialog = class extends ModalDialog.ModalDialog { ++ constructor(settings) { ++ super({ ++ styleClass: 'end-session-dialog', ++ destroyOnClose: false ++ }); ++ ++ this._gracePeriod = settings.get_uint('grace-period'); ++ this._gracePeriod = Math.min(Math.max(10, this._gracePeriod), 24 * 60); ++ this._lastWarningPeriod = settings.get_uint('last-warning-period'); ++ this._lastWarningPeriod = Math.min( ++ Math.max(1, this._lastWarningPeriod), ++ this._gracePeriod - 1); ++ this._lastWarnings = settings.get_uint('last-warnings'); ++ this._lastWarnings = Math.min( ++ Math.max(1, this._lastWarnings), ++ Math.floor((this._gracePeriod - 1) / this._lastWarningPeriod)); ++ ++ let messageLayout = new St.BoxLayout({ ++ vertical: true, ++ style_class: 'end-session-dialog-layout' ++ }); ++ this.contentLayout.add(messageLayout, { ++ x_fill: true, ++ y_fill: true, ++ y_expand: true ++ }); ++ ++ let subjectLabel = new St.Label({ ++ style_class: 'end-session-dialog-subject', ++ style: 'padding-bottom: 1em;', ++ text: _('Important security updates') ++ }); ++ messageLayout.add(subjectLabel, { ++ x_fill: false, ++ y_fill: false, ++ x_align: St.Align.START, ++ y_align: St.Align.START ++ }); ++ ++ this._detailLabel = new St.Label({ ++ style_class: 'end-session-dialog-description', ++ style: 'padding-bottom: 0em;', ++ text: getDetailText(this._gracePeriod) ++ }); ++ this._detailLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; ++ this._detailLabel.clutter_text.line_wrap = true; ++ ++ messageLayout.add(this._detailLabel, { ++ y_fill: true, ++ y_align: St.Align.START ++ }); ++ ++ let buttons = [{ ++ action: this.close.bind(this), ++ label: _('Close'), ++ key: Clutter.Escape ++ }, { ++ action: this._done.bind(this), ++ label: _('Restart & Install') ++ }]; ++ ++ this.setButtons(buttons); ++ ++ this._openTimeoutId = 0; ++ this.connect('destroy', this._clearOpenTimeout.bind(this)); ++ ++ this._startTimer(); ++ } ++ ++ _clearOpenTimeout() { ++ if (this._openTimeoutId > 0) { ++ GLib.source_remove(this._openTimeoutId); ++ this._openTimeoutId = 0; ++ } ++ } ++ ++ tryOpen() { ++ if (this._openTimeoutId > 0 || this.open()) ++ return; ++ ++ this._openTimeoutId = GLib.timeout_add_seconds( ++ GLib.PRIORITY_DEFAULT, 1, () => { ++ if (!this.open()) ++ return GLib.SOURCE_CONTINUE; ++ ++ this._clearOpenTimeout(); ++ return GLib.SOURCE_REMOVE; ++ }); ++ } ++ ++ _startTimer() { ++ this._secondsLeft = this._gracePeriod * 60; ++ ++ this._timerId = GLib.timeout_add_seconds( ++ GLib.PRIORITY_DEFAULT, 1, () => { ++ this._secondsLeft -= 1; ++ let minutesLeft = this._secondsLeft / 60; ++ let periodLeft = Math.floor(minutesLeft); ++ ++ if (this._secondsLeft == 60 || ++ (periodLeft > 0 && periodLeft <= this._lastWarningPeriod * this._lastWarnings && ++ minutesLeft % this._lastWarningPeriod == 0)) { ++ this.tryOpen(); ++ this._detailLabel.text = getDetailText(periodLeft); ++ } ++ ++ if (this._secondsLeft > 0) { ++ if (this._secondsLeft < 60) { ++ let seconds = EndSessionDialog._roundSecondsToInterval( ++ this._gracePeriod * 60, this._secondsLeft, 10); ++ this._detailLabel.text = ++ _('Important security updates need to be installed now.\n') + ++ ngettext( ++ 'This computer will restart in %d second.', ++ 'This computer will restart in %d seconds.', ++ seconds).format(seconds); ++ } ++ return GLib.SOURCE_CONTINUE; ++ } ++ ++ this._done(); ++ return GLib.SOURCE_REMOVE; ++ }); ++ this.connect('destroy', () => { ++ if (this._timerId > 0) { ++ GLib.source_remove(this._timerId); ++ this._timerId = 0; ++ } ++ }); ++ } ++ ++ _done() { ++ this.emit('done'); ++ this.destroy(); ++ } ++ ++ getState() { ++ return [this._gracePeriod, this._lastWarningPeriod, this._lastWarnings, this._secondsLeft]; ++ } ++ ++ setState(state) { ++ [this._gracePeriod, this._lastWarningPeriod, this._lastWarnings, this._secondsLeft] = state; ++ } ++}; ++Signals.addSignalMethods(UpdatesDialog.prototype); ++ ++function showDialog() { ++ if (updatesDialog) ++ return; ++ ++ updatesDialog = new UpdatesDialog(extensionSettings); ++ updatesDialog.tryOpen(); ++ updatesDialog.connect('destroy', () => updatesDialog = null); ++ updatesDialog.connect('done', () => { ++ if (pkOfflineProxy.TriggerAction == 'power-off' || ++ pkOfflineProxy.TriggerAction == 'reboot') { ++ loginManagerProxy.RebootRemote(false); ++ } else { ++ pkOfflineProxy.TriggerRemote('reboot', (result, error) => { ++ if (!error) ++ loginManagerProxy.RebootRemote(false); ++ else ++ log('Failed to trigger offline update: %s'.format(error.message)); ++ }); ++ } ++ }); ++} ++ ++function cancelDialog(save) { ++ if (!updatesDialog) ++ return; ++ ++ if (save) { ++ let state = GLib.Variant.new('(uuuu)', updatesDialog.getState()); ++ global.set_runtime_state(Me.uuid, state); ++ } ++ updatesDialog.destroy(); ++} ++ ++function restoreExistingState() { ++ let state = global.get_runtime_state('(uuuu)', Me.uuid); ++ if (state === null) ++ return false; ++ ++ global.set_runtime_state(Me.uuid, null); ++ showDialog(); ++ updatesDialog.setState(state.deep_unpack()); ++ return true; ++} ++ ++function syncState() { ++ if (!pkOfflineProxy || !loginManagerProxy) ++ return; ++ ++ if (restoreExistingState()) ++ return; ++ ++ if (!updatesCheckInProgress && ++ securityUpdates.length > 0 && ++ pkOfflineProxy.UpdatePrepared) ++ showDialog(); ++ else ++ cancelDialog(); ++} ++ ++function doPkTransaction(callback) { ++ if (!pkProxy) ++ return; ++ ++ pkProxy.CreateTransactionRemote((result, error) => { ++ if (error) { ++ log('Error creating PackageKit transaction: %s'.format(error.message)); ++ checkUpdatesDone(); ++ return; ++ } ++ ++ new PkTransactionProxy(Gio.DBus.system, ++ 'org.freedesktop.PackageKit', ++ String(result), ++ (proxy, error) => { ++ if (!error) { ++ proxy.SetHintsRemote( ++ ['background=true', 'interactive=false'], ++ (result, error) => { ++ if (error) { ++ log('Error connecting to PackageKit: %s'.format(error.message)); ++ checkUpdatesDone(); ++ return; ++ } ++ callback(proxy); ++ }); ++ } else { ++ log('Error connecting to PackageKit: %s'.format(error.message)); ++ } ++ }); ++ }); ++} ++ ++function pkUpdatePackages(proxy) { ++ proxy.connectSignal('Finished', (p, e, params) => { ++ let [exit, runtime_] = params; ++ ++ if (exit == PkgKit.ExitEnum.CANCELLED_PRIORITY) { ++ // try again ++ checkUpdates(); ++ } else if (exit != PkgKit.ExitEnum.SUCCESS) { ++ log('UpdatePackages failed: %s'.format(PkgKit.ExitEnum.to_string(exit))); ++ } ++ ++ checkUpdatesDone(); ++ }); ++ proxy.UpdatePackagesRemote(1 << PkgKit.TransactionFlagEnum.ONLY_DOWNLOAD, securityUpdates); ++} ++ ++function pkGetUpdates(proxy) { ++ proxy.connectSignal('Package', (p, e, params) => { ++ let [info, packageId, summary_] = params; ++ ++ if (info == PkgKit.InfoEnum.SECURITY) ++ securityUpdates.push(packageId); ++ }); ++ proxy.connectSignal('Finished', (p, e, params) => { ++ let [exit, runtime_] = params; ++ ++ if (exit == PkgKit.ExitEnum.SUCCESS) { ++ if (securityUpdates.length > 0) { ++ doPkTransaction(pkUpdatePackages); ++ return; ++ } ++ } else if (exit == PkgKit.ExitEnum.CANCELLED_PRIORITY) { ++ // try again ++ checkUpdates(); ++ } else { ++ log('GetUpdates failed: %s'.format(PkgKit.ExitEnum.to_string(exit))); ++ } ++ ++ checkUpdatesDone(); ++ }); ++ proxy.GetUpdatesRemote(0); ++} ++ ++function checkUpdatesDone() { ++ updatesCheckInProgress = false; ++ if (updatesCheckRequested) { ++ updatesCheckRequested = false; ++ checkUpdates(); ++ } else { ++ syncState(); ++ } ++} ++ ++function checkUpdates() { ++ if (updatesCheckInProgress) { ++ updatesCheckRequested = true; ++ return; ++ } ++ updatesCheckInProgress = true; ++ securityUpdates = []; ++ doPkTransaction(pkGetUpdates); ++} ++ ++function initSystemProxies() { ++ new PkProxy(Gio.DBus.system, ++ 'org.freedesktop.PackageKit', ++ '/org/freedesktop/PackageKit', ++ (proxy, error) => { ++ if (!error) { ++ pkProxy = proxy; ++ let id = pkProxy.connectSignal('UpdatesChanged', checkUpdates); ++ pkProxy._signalId = id; ++ checkUpdates(); ++ } else { ++ log('Error connecting to PackageKit: %s'.format(error.message)); ++ } ++ }, ++ cancellable); ++ new PkOfflineProxy(Gio.DBus.system, ++ 'org.freedesktop.PackageKit', ++ '/org/freedesktop/PackageKit', ++ (proxy, error) => { ++ if (!error) { ++ pkOfflineProxy = proxy; ++ let id = pkOfflineProxy.connect('g-properties-changed', syncState); ++ pkOfflineProxy._signalId = id; ++ syncState(); ++ } else { ++ log('Error connecting to PackageKit: %s'.format(error.message)); ++ } ++ }, ++ cancellable); ++ new LoginManagerProxy(Gio.DBus.system, ++ 'org.freedesktop.login1', ++ '/org/freedesktop/login1', ++ (proxy, error) => { ++ if (!error) { ++ proxy.CanRebootRemote(cancellable, (result, error) => { ++ if (!error && result == 'yes') { ++ loginManagerProxy = proxy; ++ syncState(); ++ } else { ++ log('Reboot is not available'); ++ } ++ }); ++ } else { ++ log('Error connecting to Login manager: %s'.format(error.message)); ++ } ++ }, ++ cancellable); ++} ++ ++function enable() { ++ cancellable = new Gio.Cancellable(); ++ extensionSettings = ExtensionUtils.getSettings(); ++ Polkit.Permission.new('org.freedesktop.packagekit.trigger-offline-update', ++ null, ++ cancellable, ++ (p, result) => { ++ try { ++ let permission = Polkit.Permission.new_finish(result); ++ if (permission && permission.allowed) ++ initSystemProxies(); ++ else ++ throw (new Error('not allowed')); ++ } catch (e) { ++ log('No permission to trigger offline updates: %s'.format(e.toString())); ++ } ++ }); ++} ++ ++function disable() { ++ cancelDialog(true); ++ cancellable.cancel(); ++ cancellable = null; ++ extensionSettings = null; ++ updatesDialog = null; ++ loginManagerProxy = null; ++ if (pkOfflineProxy) { ++ pkOfflineProxy.disconnect(pkOfflineProxy._signalId); ++ pkOfflineProxy = null; ++ } ++ if (pkProxy) { ++ pkProxy.disconnectSignal(pkProxy._signalId); ++ pkProxy = null; ++ } ++} +diff --git a/extensions/updates-dialog/meson.build b/extensions/updates-dialog/meson.build +new file mode 100644 +index 00000000..585c02da +--- /dev/null ++++ b/extensions/updates-dialog/meson.build +@@ -0,0 +1,7 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') +diff --git a/extensions/updates-dialog/metadata.json.in b/extensions/updates-dialog/metadata.json.in +new file mode 100644 +index 00000000..9946abb5 +--- /dev/null ++++ b/extensions/updates-dialog/metadata.json.in +@@ -0,0 +1,10 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Updates Dialog", ++"description": "Shows a modal dialog when there are software updates.", ++"shell-version": [ "@shell_current@" ], ++"url": "http://rtcm.fedorapeople.org/updates-dialog" ++} +diff --git a/extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml b/extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml +new file mode 100644 +index 00000000..c08d33c4 +--- /dev/null ++++ b/extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml +@@ -0,0 +1,30 @@ ++ ++ ++ ++ ++ 300 ++ Grace period in minutes ++ ++ When the grace period is over, the computer will automatically ++ reboot and install security updates. ++ ++ ++ ++ 10 ++ Last warning dialog period ++ ++ A last warning dialog is displayed this many minutes before ++ the automatic reboot. ++ ++ ++ ++ 1 ++ Number of last warning dialogs ++ ++ How many warning dialogs are displayed. Each is displayed at ++ 'last-warning-period' minute intervals. ++ ++ ++ ++ +diff --git a/extensions/updates-dialog/stylesheet.css b/extensions/updates-dialog/stylesheet.css +new file mode 100644 +index 00000000..25134b65 +--- /dev/null ++++ b/extensions/updates-dialog/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index e8e00dce..d129e6cd 100644 +--- a/meson.build ++++ b/meson.build +@@ -53,6 +53,7 @@ all_extensions += [ + 'native-window-placement', + 'panel-favorites', + 'top-icons', ++ 'updates-dialog', + 'user-theme' + ] + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 9c1438ac..55f0e9aa 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -10,6 +10,8 @@ extensions/native-window-placement/org.gnome.shell.extensions.native-window-plac + extensions/places-menu/extension.js + extensions/places-menu/placeDisplay.js + extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml ++extensions/updates-dialog/extension.js ++extensions/updates-dialog/org.gnome.shell.extensions.updates-dialog.gschema.xml + extensions/user-theme/extension.js + extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml + extensions/window-list/extension.js +-- +2.38.1 + + +From 0ba4b86fa5f73bccd3ab1984d9deef0d39f656c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 1 Jun 2017 23:57:14 +0200 +Subject: [PATCH 05/11] Add no-hot-corner extension + +--- + extensions/no-hot-corner/extension.js | 31 +++++++++++++++++++++++ + extensions/no-hot-corner/meson.build | 5 ++++ + extensions/no-hot-corner/metadata.json.in | 9 +++++++ + extensions/no-hot-corner/stylesheet.css | 1 + + meson.build | 1 + + 5 files changed, 47 insertions(+) + create mode 100644 extensions/no-hot-corner/extension.js + create mode 100644 extensions/no-hot-corner/meson.build + create mode 100644 extensions/no-hot-corner/metadata.json.in + create mode 100644 extensions/no-hot-corner/stylesheet.css + +diff --git a/extensions/no-hot-corner/extension.js b/extensions/no-hot-corner/extension.js +new file mode 100644 +index 00000000..e7a0d637 +--- /dev/null ++++ b/extensions/no-hot-corner/extension.js +@@ -0,0 +1,31 @@ ++const Main = imports.ui.main; ++ ++let _id; ++ ++function _disableHotCorners() { ++ // Disables all hot corners ++ Main.layoutManager.hotCorners.forEach(function(hotCorner) { ++ if (!hotCorner) { ++ return; ++ } ++ ++ hotCorner._toggleOverview = function() {}; ++ hotCorner._pressureBarrier._trigger = function() {}; ++ }); ++} ++ ++function init() { ++} ++ ++function enable() { ++ _disableHotCorners(); ++ // Hot corners may be re-created afterwards (for example, If there's a monitor change). ++ // So we catch all changes. ++ _id = Main.layoutManager.connect('hot-corners-changed', _disableHotCorners); ++} ++ ++function disable() { ++ // Disconnects the callback and re-creates the hot corners ++ Main.layoutManager.disconnect(_id); ++ Main.layoutManager._updateHotCorners(); ++} +diff --git a/extensions/no-hot-corner/meson.build b/extensions/no-hot-corner/meson.build +new file mode 100644 +index 00000000..48504f63 +--- /dev/null ++++ b/extensions/no-hot-corner/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/no-hot-corner/metadata.json.in b/extensions/no-hot-corner/metadata.json.in +new file mode 100644 +index 00000000..406d83b6 +--- /dev/null ++++ b/extensions/no-hot-corner/metadata.json.in +@@ -0,0 +1,9 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"name": "No Topleft Hot Corner", ++"description": "Disable the hot corner in the top left; you can still reach the overview by clicking the Activities button or pressing the dedicated key.", ++"shell-version": [ "@shell_current@" ], ++"url": "https://github.com/HROMANO/nohotcorner/", ++"version": 15 ++} +diff --git a/extensions/no-hot-corner/stylesheet.css b/extensions/no-hot-corner/stylesheet.css +new file mode 100644 +index 00000000..25134b65 +--- /dev/null ++++ b/extensions/no-hot-corner/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index d129e6cd..6f27f460 100644 +--- a/meson.build ++++ b/meson.build +@@ -51,6 +51,7 @@ all_extensions += [ + 'auto-move-windows', + 'dash-to-dock', + 'native-window-placement', ++ 'no-hot-corner', + 'panel-favorites', + 'top-icons', + 'updates-dialog', +-- +2.38.1 + + +From f56b4374904cdfd8e1790dc3cf5080b60f30ebea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 26 Mar 2019 19:44:43 +0100 +Subject: [PATCH 06/11] Add window-grouper extension + +--- + extensions/window-grouper/extension.js | 109 ++++++++++ + extensions/window-grouper/meson.build | 8 + + extensions/window-grouper/metadata.json.in | 11 + + ...hell.extensions.window-grouper.gschema.xml | 9 + + extensions/window-grouper/prefs.js | 191 ++++++++++++++++++ + extensions/window-grouper/stylesheet.css | 1 + + meson.build | 3 +- + 7 files changed, 331 insertions(+), 1 deletion(-) + create mode 100644 extensions/window-grouper/extension.js + create mode 100644 extensions/window-grouper/meson.build + create mode 100644 extensions/window-grouper/metadata.json.in + create mode 100644 extensions/window-grouper/org.gnome.shell.extensions.window-grouper.gschema.xml + create mode 100644 extensions/window-grouper/prefs.js + create mode 100644 extensions/window-grouper/stylesheet.css + +diff --git a/extensions/window-grouper/extension.js b/extensions/window-grouper/extension.js +new file mode 100644 +index 00000000..f66a7641 +--- /dev/null ++++ b/extensions/window-grouper/extension.js +@@ -0,0 +1,109 @@ ++// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- ++/* exported init */ ++ ++const { Shell } = imports.gi; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++ ++class WindowMover { ++ constructor() { ++ this._settings = ExtensionUtils.getSettings(); ++ this._appSystem = Shell.AppSystem.get_default(); ++ this._appConfigs = new Set(); ++ this._appData = new Map(); ++ ++ this._appsChangedId = this._appSystem.connect( ++ 'installed-changed', this._updateAppData.bind(this)); ++ ++ this._settings.connect('changed', this._updateAppConfigs.bind(this)); ++ this._updateAppConfigs(); ++ } ++ ++ _updateAppConfigs() { ++ this._appConfigs.clear(); ++ ++ this._settings.get_strv('application-list').forEach(appId => { ++ this._appConfigs.add(appId); ++ }); ++ ++ this._updateAppData(); ++ } ++ ++ _updateAppData() { ++ let ids = [...this._appConfigs.values()]; ++ let removedApps = [...this._appData.keys()].filter( ++ a => !ids.includes(a.id) ++ ); ++ removedApps.forEach(app => { ++ app.disconnect(this._appData.get(app).windowsChangedId); ++ this._appData.delete(app); ++ }); ++ ++ let addedApps = ids.map(id => this._appSystem.lookup_app(id)).filter( ++ app => app != null && !this._appData.has(app) ++ ); ++ addedApps.forEach(app => { ++ let data = { ++ windows: app.get_windows(), ++ windowsChangedId: app.connect( ++ 'windows-changed', this._appWindowsChanged.bind(this)) ++ }; ++ this._appData.set(app, data); ++ }); ++ } ++ ++ destroy() { ++ if (this._appsChangedId) { ++ this._appSystem.disconnect(this._appsChangedId); ++ this._appsChangedId = 0; ++ } ++ ++ if (this._settings) { ++ this._settings.run_dispose(); ++ this._settings = null; ++ } ++ ++ this._appConfigs.clear(); ++ this._updateAppData(); ++ } ++ ++ _appWindowsChanged(app) { ++ let data = this._appData.get(app); ++ let windows = app.get_windows(); ++ ++ // If get_compositor_private() returns non-NULL on a removed windows, ++ // the window still exists and is just moved to a different workspace ++ // or something; assume it'll be added back immediately, so keep it ++ // to avoid moving it again ++ windows.push(...data.windows.filter( ++ w => !windows.includes(w) && w.get_compositor_private() != null ++ )); ++ ++ windows.filter(w => !data.windows.includes(w)).forEach(window => { ++ let leader = data.windows.find(w => w.get_pid() == window.get_pid()); ++ if (leader) ++ window.change_workspace(leader.get_workspace()); ++ }); ++ data.windows = windows; ++ } ++} ++ ++class Extension { ++ constructor() { ++ this._winMover = null; ++ } ++ ++ enable() { ++ this._winMover = new WindowMover(); ++ } ++ ++ disable() { ++ this._winMover.destroy(); ++ this._winMover = null; ++ } ++} ++ ++function init() { ++ ExtensionUtils.initTranslations(); ++ return new Extension(); ++} +diff --git a/extensions/window-grouper/meson.build b/extensions/window-grouper/meson.build +new file mode 100644 +index 00000000..c55a7830 +--- /dev/null ++++ b/extensions/window-grouper/meson.build +@@ -0,0 +1,8 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_sources += files('prefs.js') ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') +diff --git a/extensions/window-grouper/metadata.json.in b/extensions/window-grouper/metadata.json.in +new file mode 100644 +index 00000000..aa202c8f +--- /dev/null ++++ b/extensions/window-grouper/metadata.json.in +@@ -0,0 +1,11 @@ ++{ ++ "extension-id": "@extension_id@", ++ "uuid": "@uuid@", ++ "settings-schema": "@gschemaname@", ++ "gettext-domain": "@gettext_domain@", ++ "name": "Window grouper", ++ "description": "Keep windows that belong to the same process on the same workspace.", ++ "shell-version": [ "@shell_current@" ], ++ "original-authors": [ "fmuellner@redhat.com" ], ++ "url": "@url@" ++} +diff --git a/extensions/window-grouper/org.gnome.shell.extensions.window-grouper.gschema.xml b/extensions/window-grouper/org.gnome.shell.extensions.window-grouper.gschema.xml +new file mode 100644 +index 00000000..ee052a6e +--- /dev/null ++++ b/extensions/window-grouper/org.gnome.shell.extensions.window-grouper.gschema.xml +@@ -0,0 +1,9 @@ ++ ++ ++ ++ [ ] ++ Application that should be grouped ++ A list of application ids ++ ++ ++ +diff --git a/extensions/window-grouper/prefs.js b/extensions/window-grouper/prefs.js +new file mode 100644 +index 00000000..d7b748ed +--- /dev/null ++++ b/extensions/window-grouper/prefs.js +@@ -0,0 +1,191 @@ ++// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- ++/* exported init buildPrefsWidget */ ++ ++const { Gio, GObject, Gtk } = imports.gi; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++const N_ = e => e; ++ ++const SETTINGS_KEY = 'application-list'; ++ ++const Columns = { ++ APPINFO: 0, ++ DISPLAY_NAME: 1, ++ ICON: 2 ++}; ++ ++const Widget = GObject.registerClass({ ++ GTypeName: 'WindowGrouperPrefsWidget', ++}, class Widget extends Gtk.Grid { ++ _init(params) { ++ super._init(params); ++ this.set_orientation(Gtk.Orientation.VERTICAL); ++ ++ this._settings = ExtensionUtils.getSettings(); ++ this._settings.connect('changed', this._refresh.bind(this)); ++ this._changedPermitted = false; ++ ++ this._store = new Gtk.ListStore(); ++ this._store.set_column_types([Gio.AppInfo, GObject.TYPE_STRING, Gio.Icon]); ++ ++ let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN }); ++ scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); ++ this.add(scrolled); ++ ++ ++ this._treeView = new Gtk.TreeView({ ++ model: this._store, ++ headers_visible: false, ++ hexpand: true, ++ vexpand: true ++ }); ++ this._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE); ++ ++ let appColumn = new Gtk.TreeViewColumn({ ++ sort_column_id: Columns.DISPLAY_NAME, ++ spacing: 12 ++ }); ++ let iconRenderer = new Gtk.CellRendererPixbuf({ ++ stock_size: Gtk.IconSize.DIALOG, ++ xpad: 12, ++ ypad: 12 ++ }); ++ appColumn.pack_start(iconRenderer, false); ++ appColumn.add_attribute(iconRenderer, 'gicon', Columns.ICON); ++ let nameRenderer = new Gtk.CellRendererText(); ++ appColumn.pack_start(nameRenderer, true); ++ appColumn.add_attribute(nameRenderer, 'text', Columns.DISPLAY_NAME); ++ this._treeView.append_column(appColumn); ++ ++ scrolled.add(this._treeView); ++ ++ let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR }); ++ toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR); ++ this.add(toolbar); ++ ++ let newButton = new Gtk.ToolButton({ ++ icon_name: 'list-add-symbolic' ++ }); ++ newButton.connect('clicked', this._createNew.bind(this)); ++ toolbar.add(newButton); ++ ++ let delButton = new Gtk.ToolButton({ ++ icon_name: 'list-remove-symbolic' ++ }); ++ delButton.connect('clicked', this._deleteSelected.bind(this)); ++ toolbar.add(delButton); ++ ++ let selection = this._treeView.get_selection(); ++ selection.connect('changed', () => { ++ delButton.sensitive = selection.count_selected_rows() > 0; ++ }); ++ delButton.sensitive = selection.count_selected_rows() > 0; ++ ++ this._changedPermitted = true; ++ this._refresh(); ++ } ++ ++ _createNew() { ++ let dialog = new Gtk.AppChooserDialog({ ++ heading: _('Select an application for which grouping should apply'), ++ transient_for: this.get_toplevel(), ++ modal: true ++ }); ++ ++ dialog.get_widget().show_all = true; ++ ++ dialog.connect('response', (dialog, id) => { ++ if (id != Gtk.ResponseType.OK) { ++ dialog.destroy(); ++ return; ++ } ++ ++ let appInfo = dialog.get_app_info(); ++ if (!appInfo) { ++ dialog.destroy(); ++ return; ++ } ++ ++ this._changedPermitted = false; ++ this._appendItem(appInfo.get_id()); ++ this._changedPermitted = true; ++ ++ let iter = this._store.append(); ++ this._store.set(iter, ++ [Columns.APPINFO, Columns.ICON, Columns.DISPLAY_NAME], ++ [appInfo, appInfo.get_icon(), appInfo.get_display_name()]); ++ ++ dialog.destroy(); ++ }); ++ dialog.show_all(); ++ } ++ ++ _deleteSelected() { ++ let [any, model_, iter] = this._treeView.get_selection().get_selected(); ++ ++ if (any) { ++ let appInfo = this._store.get_value(iter, Columns.APPINFO); ++ ++ this._changedPermitted = false; ++ this._removeItem(appInfo.get_id()); ++ this._changedPermitted = true; ++ this._store.remove(iter); ++ } ++ } ++ ++ _refresh() { ++ if (!this._changedPermitted) ++ // Ignore this notification, model is being modified outside ++ return; ++ ++ this._store.clear(); ++ ++ let currentItems = this._settings.get_strv(SETTINGS_KEY); ++ let validItems = []; ++ for (let i = 0; i < currentItems.length; i++) { ++ let id = currentItems[i]; ++ let appInfo = Gio.DesktopAppInfo.new(id); ++ if (!appInfo) ++ continue; ++ validItems.push(currentItems[i]); ++ ++ let iter = this._store.append(); ++ this._store.set(iter, ++ [Columns.APPINFO, Columns.ICON, Columns.DISPLAY_NAME], ++ [appInfo, appInfo.get_icon(), appInfo.get_display_name()]); ++ } ++ ++ if (validItems.length != currentItems.length) // some items were filtered out ++ this._settings.set_strv(SETTINGS_KEY, validItems); ++ } ++ ++ _appendItem(id) { ++ let currentItems = this._settings.get_strv(SETTINGS_KEY); ++ currentItems.push(id); ++ this._settings.set_strv(SETTINGS_KEY, currentItems); ++ } ++ ++ _removeItem(id) { ++ let currentItems = this._settings.get_strv(SETTINGS_KEY); ++ let index = currentItems.indexOf(id); ++ ++ if (index < 0) ++ return; ++ currentItems.splice(index, 1); ++ this._settings.set_strv(SETTINGS_KEY, currentItems); ++ } ++}); ++ ++ ++function init() { ++ ExtensionUtils.initTranslations(); ++} ++ ++function buildPrefsWidget() { ++ let widget = new Widget({ margin: 12 }); ++ widget.show_all(); ++ ++ return widget; ++} +diff --git a/extensions/window-grouper/stylesheet.css b/extensions/window-grouper/stylesheet.css +new file mode 100644 +index 00000000..25134b65 +--- /dev/null ++++ b/extensions/window-grouper/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index 6f27f460..4b9d138c 100644 +--- a/meson.build ++++ b/meson.build +@@ -55,7 +55,8 @@ all_extensions += [ + 'panel-favorites', + 'top-icons', + 'updates-dialog', +- 'user-theme' ++ 'user-theme', ++ 'window-grouper' + ] + + enabled_extensions = get_option('enable_extensions') +-- +2.38.1 + + +From 25c4999ff6adf19a32bab2a4d6cccae42520563b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 26 Mar 2019 21:32:09 +0100 +Subject: [PATCH 07/11] Add disable-screenshield extension + +--- + extensions/disable-screenshield/extension.js | 27 +++++++++++++++++++ + extensions/disable-screenshield/meson.build | 5 ++++ + .../disable-screenshield/metadata.json.in | 9 +++++++ + .../disable-screenshield/stylesheet.css | 1 + + meson.build | 1 + + 5 files changed, 43 insertions(+) + create mode 100644 extensions/disable-screenshield/extension.js + create mode 100644 extensions/disable-screenshield/meson.build + create mode 100644 extensions/disable-screenshield/metadata.json.in + create mode 100644 extensions/disable-screenshield/stylesheet.css + +diff --git a/extensions/disable-screenshield/extension.js b/extensions/disable-screenshield/extension.js +new file mode 100644 +index 00000000..91204c0f +--- /dev/null ++++ b/extensions/disable-screenshield/extension.js +@@ -0,0 +1,27 @@ ++/* exported enable disable */ ++ ++const ScreenShield = imports.ui.screenShield; ++ ++let _onUserBecameActiveOrig; ++ ++function _onUserBecameActiveInjected() { ++ this.idleMonitor.remove_watch(this._becameActiveId); ++ this._becameActiveId = 0; ++ ++ this._longLightbox.hide(); ++ this._shortLightbox.hide(); ++ ++ this.deactivate(false); ++} ++ ++function enable() { ++ _onUserBecameActiveOrig = ++ ScreenShield.ScreenShield.prototype._onUserBecameActive; ++ ScreenShield.ScreenShield.prototype._onUserBecameActive = ++ _onUserBecameActiveInjected; ++} ++ ++function disable() { ++ ScreenShield.ScreenShield.prototype._onUserBecameActive = ++ _onUserBecameActiveOrig; ++} +diff --git a/extensions/disable-screenshield/meson.build b/extensions/disable-screenshield/meson.build +new file mode 100644 +index 00000000..48504f63 +--- /dev/null ++++ b/extensions/disable-screenshield/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/disable-screenshield/metadata.json.in b/extensions/disable-screenshield/metadata.json.in +new file mode 100644 +index 00000000..074429f0 +--- /dev/null ++++ b/extensions/disable-screenshield/metadata.json.in +@@ -0,0 +1,9 @@ ++{ ++ "extension-id": "@extension_id@", ++ "uuid": "@uuid@", ++ "name": "Disable Screen Shield", ++ "description": "Disable screen shield when screen lock is disabled", ++ "shell-version": [ "@shell_current@" ], ++ "original-authors": [ "lgpasquale@gmail.com" ], ++ "url": "@url@" ++} +diff --git a/extensions/disable-screenshield/stylesheet.css b/extensions/disable-screenshield/stylesheet.css +new file mode 100644 +index 00000000..25134b65 +--- /dev/null ++++ b/extensions/disable-screenshield/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index 4b9d138c..cf855a01 100644 +--- a/meson.build ++++ b/meson.build +@@ -50,6 +50,7 @@ all_extensions = default_extensions + all_extensions += [ + 'auto-move-windows', + 'dash-to-dock', ++ 'disable-screenshield', + 'native-window-placement', + 'no-hot-corner', + 'panel-favorites', +-- +2.38.1 + + +From 59604979f6ba48b7ff8d1616ab9df739dcf46a20 Mon Sep 17 00:00:00 2001 +From: Carlos Soriano +Date: Mon, 13 Aug 2018 17:28:41 +0200 +Subject: [PATCH 08/11] Add desktop icons extension + +--- + .../desktop-icons/createFolderDialog.js | 164 ++++ + extensions/desktop-icons/createThumbnail.js | 35 + + extensions/desktop-icons/dbusUtils.js | 103 +++ + extensions/desktop-icons/desktopGrid.js | 692 +++++++++++++++ + extensions/desktop-icons/desktopIconsUtil.js | 123 +++ + extensions/desktop-icons/desktopManager.js | 754 ++++++++++++++++ + extensions/desktop-icons/extension.js | 71 ++ + extensions/desktop-icons/fileItem.js | 830 ++++++++++++++++++ + extensions/desktop-icons/meson.build | 19 + + extensions/desktop-icons/metadata.json.in | 11 + + extensions/desktop-icons/po/LINGUAS | 19 + + extensions/desktop-icons/po/POTFILES.in | 4 + + extensions/desktop-icons/po/cs.po | 195 ++++ + extensions/desktop-icons/po/da.po | 159 ++++ + extensions/desktop-icons/po/de.po | 192 ++++ + extensions/desktop-icons/po/es.po | 218 +++++ + extensions/desktop-icons/po/fi.po | 191 ++++ + extensions/desktop-icons/po/fr.po | 164 ++++ + extensions/desktop-icons/po/fur.po | 187 ++++ + extensions/desktop-icons/po/hr.po | 186 ++++ + extensions/desktop-icons/po/hu.po | 190 ++++ + extensions/desktop-icons/po/id.po | 190 ++++ + extensions/desktop-icons/po/it.po | 189 ++++ + extensions/desktop-icons/po/ja.po | 187 ++++ + extensions/desktop-icons/po/meson.build | 1 + + extensions/desktop-icons/po/nl.po | 188 ++++ + extensions/desktop-icons/po/pl.po | 193 ++++ + extensions/desktop-icons/po/pt_BR.po | 199 +++++ + extensions/desktop-icons/po/ru.po | 153 ++++ + extensions/desktop-icons/po/sv.po | 197 +++++ + extensions/desktop-icons/po/tr.po | 191 ++++ + extensions/desktop-icons/po/zh_TW.po | 135 +++ + extensions/desktop-icons/prefs.js | 159 ++++ + extensions/desktop-icons/schemas/meson.build | 6 + + ...shell.extensions.desktop-icons.gschema.xml | 25 + + extensions/desktop-icons/stylesheet.css | 38 + + meson.build | 1 + + po/ca.po | 194 ++++ + po/cs.po | 198 +++++ + po/da.po | 194 ++++ + po/de.po | 195 ++++ + po/en_GB.po | 204 ++++- + po/es.po | 243 ++++- + po/fi.po | 209 ++++- + po/fr.po | 167 ++++ + po/fur.po | 198 ++++- + po/hr.po | 195 ++++ + po/hu.po | 195 ++++ + po/id.po | 197 +++++ + po/it.po | 192 ++++ + po/ja.po | 210 ++++- + po/nl.po | 191 ++++ + po/pl.po | 196 +++++ + po/pt_BR.po | 216 ++++- + po/ru.po | 156 ++++ + po/sv.po | 204 +++++ + po/tr.po | 194 ++++ + po/zh_TW.po | 149 +++- + 58 files changed, 10608 insertions(+), 48 deletions(-) + create mode 100644 extensions/desktop-icons/createFolderDialog.js + create mode 100755 extensions/desktop-icons/createThumbnail.js + create mode 100644 extensions/desktop-icons/dbusUtils.js + create mode 100644 extensions/desktop-icons/desktopGrid.js + create mode 100644 extensions/desktop-icons/desktopIconsUtil.js + create mode 100644 extensions/desktop-icons/desktopManager.js + create mode 100644 extensions/desktop-icons/extension.js + create mode 100644 extensions/desktop-icons/fileItem.js + create mode 100644 extensions/desktop-icons/meson.build + create mode 100644 extensions/desktop-icons/metadata.json.in + create mode 100644 extensions/desktop-icons/po/LINGUAS + create mode 100644 extensions/desktop-icons/po/POTFILES.in + create mode 100644 extensions/desktop-icons/po/cs.po + create mode 100644 extensions/desktop-icons/po/da.po + create mode 100644 extensions/desktop-icons/po/de.po + create mode 100644 extensions/desktop-icons/po/es.po + create mode 100644 extensions/desktop-icons/po/fi.po + create mode 100644 extensions/desktop-icons/po/fr.po + create mode 100644 extensions/desktop-icons/po/fur.po + create mode 100644 extensions/desktop-icons/po/hr.po + create mode 100644 extensions/desktop-icons/po/hu.po + create mode 100644 extensions/desktop-icons/po/id.po + create mode 100644 extensions/desktop-icons/po/it.po + create mode 100644 extensions/desktop-icons/po/ja.po + create mode 100644 extensions/desktop-icons/po/meson.build + create mode 100644 extensions/desktop-icons/po/nl.po + create mode 100644 extensions/desktop-icons/po/pl.po + create mode 100644 extensions/desktop-icons/po/pt_BR.po + create mode 100644 extensions/desktop-icons/po/ru.po + create mode 100644 extensions/desktop-icons/po/sv.po + create mode 100644 extensions/desktop-icons/po/tr.po + create mode 100644 extensions/desktop-icons/po/zh_TW.po + create mode 100644 extensions/desktop-icons/prefs.js + create mode 100644 extensions/desktop-icons/schemas/meson.build + create mode 100644 extensions/desktop-icons/schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml + create mode 100644 extensions/desktop-icons/stylesheet.css + +diff --git a/extensions/desktop-icons/createFolderDialog.js b/extensions/desktop-icons/createFolderDialog.js +new file mode 100644 +index 00000000..f3e40e9c +--- /dev/null ++++ b/extensions/desktop-icons/createFolderDialog.js +@@ -0,0 +1,164 @@ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2019 Andrea Azzaronea ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const { Clutter, GObject, GLib, Gio, St } = imports.gi; ++ ++const Signals = imports.signals; ++ ++const Dialog = imports.ui.dialog; ++const Gettext = imports.gettext.domain('desktop-icons'); ++const ModalDialog = imports.ui.modalDialog; ++const ShellEntry = imports.ui.shellEntry; ++const Tweener = imports.ui.tweener; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const DesktopIconsUtil = Me.imports.desktopIconsUtil; ++const Extension = Me.imports.extension; ++ ++const _ = Gettext.gettext; ++ ++const DIALOG_GROW_TIME = 0.1; ++ ++var CreateFolderDialog = class extends ModalDialog.ModalDialog { ++ ++ constructor() { ++ super({ styleClass: 'create-folder-dialog' }); ++ ++ this._buildLayout(); ++ } ++ ++ _buildLayout() { ++ let label = new St.Label({ style_class: 'create-folder-dialog-label', ++ text: _('New folder name') }); ++ this.contentLayout.add(label, { x_align: St.Align.START }); ++ ++ this._entry = new St.Entry({ style_class: 'create-folder-dialog-entry', ++ can_focus: true }); ++ this._entry.clutter_text.connect('activate', this._onEntryActivate.bind(this)); ++ this._entry.clutter_text.connect('text-changed', this._onTextChanged.bind(this)); ++ ShellEntry.addContextMenu(this._entry); ++ this.contentLayout.add(this._entry); ++ this.setInitialKeyFocus(this._entry); ++ ++ this._errorBox = new St.BoxLayout({ style_class: 'create-folder-dialog-error-box', ++ visible: false }); ++ this.contentLayout.add(this._errorBox, { expand: true }); ++ ++ this._errorMessage = new St.Label({ style_class: 'create-folder-dialog-error-label' }); ++ this._errorMessage.clutter_text.line_wrap = true; ++ this._errorBox.add(this._errorMessage, { expand: true, ++ x_align: St.Align.START, ++ x_fill: false, ++ y_align: St.Align.MIDDLE, ++ y_fill: false }); ++ ++ this._createButton = this.addButton({ action: this._onCreateButton.bind(this), ++ label: _('Create') }); ++ this.addButton({ action: this.close.bind(this), ++ label: _('Cancel'), ++ key: Clutter.Escape }); ++ this._onTextChanged(); ++ } ++ ++ _showError(message) { ++ this._errorMessage.set_text(message); ++ ++ if (!this._errorBox.visible) { ++ let [errorBoxMinHeight, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1); ++ let parentActor = this._errorBox.get_parent(); ++ ++ Tweener.addTween(parentActor, ++ { height: parentActor.height + errorBoxNaturalHeight, ++ time: DIALOG_GROW_TIME, ++ transition: 'easeOutQuad', ++ onComplete: () => { ++ parentActor.set_height(-1); ++ this._errorBox.show(); ++ } ++ }); ++ } ++ } ++ ++ _hideError() { ++ if (this._errorBox.visible) { ++ let [errorBoxMinHeight, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1); ++ let parentActor = this._errorBox.get_parent(); ++ ++ Tweener.addTween(parentActor, ++ { height: parentActor.height - errorBoxNaturalHeight, ++ time: DIALOG_GROW_TIME, ++ transition: 'easeOutQuad', ++ onComplete: () => { ++ parentActor.set_height(-1); ++ this._errorBox.hide(); ++ this._errorMessage.set_text(''); ++ } ++ }); ++ } ++ } ++ ++ _onCreateButton() { ++ this._onEntryActivate(); ++ } ++ ++ _onEntryActivate() { ++ if (!this._createButton.reactive) ++ return; ++ ++ this.emit('response', this._entry.get_text()); ++ this.close(); ++ } ++ ++ _onTextChanged() { ++ let text = this._entry.get_text(); ++ let is_valid = true; ++ ++ let found_name = false; ++ for(let name of Extension.desktopManager.getDesktopFileNames()) { ++ if (name === text) { ++ found_name = true; ++ break; ++ } ++ } ++ ++ if (text.trim().length == 0) { ++ is_valid = false; ++ this._hideError(); ++ } else if (text.includes('/')) { ++ is_valid = false; ++ this._showError(_('Folder names cannot contain “/”.')); ++ } else if (text === '.') { ++ is_valid = false; ++ this._showError(_('A folder cannot be called “.”.')); ++ } else if (text === '..') { ++ is_valid = false; ++ this._showError(_('A folder cannot be called “..”.')); ++ } else if (text.startsWith('.')) { ++ this._showError(_('Folders with “.” at the beginning of their name are hidden.')); ++ } else if (found_name) { ++ this._showError(_('There is already a file or folder with that name.')); ++ is_valid = false; ++ } else { ++ this._hideError(); ++ } ++ ++ this._createButton.reactive = is_valid; ++ } ++}; ++Signals.addSignalMethods(CreateFolderDialog.prototype); +diff --git a/extensions/desktop-icons/createThumbnail.js b/extensions/desktop-icons/createThumbnail.js +new file mode 100755 +index 00000000..212f6b79 +--- /dev/null ++++ b/extensions/desktop-icons/createThumbnail.js +@@ -0,0 +1,35 @@ ++#!/usr/bin/gjs ++ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2018 Sergio Costas ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const GnomeDesktop = imports.gi.GnomeDesktop; ++const Gio = imports.gi.Gio; ++ ++let thumbnailFactory = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE); ++ ++let file = Gio.File.new_for_path(ARGV[0]); ++let fileUri = file.get_uri(); ++ ++let fileInfo = file.query_info('standard::content-type,time::modified', Gio.FileQueryInfoFlags.NONE, null); ++let modifiedTime = fileInfo.get_attribute_uint64('time::modified'); ++let thumbnailPixbuf = thumbnailFactory.generate_thumbnail(fileUri, fileInfo.get_content_type()); ++if (thumbnailPixbuf == null) ++ thumbnailFactory.create_failed_thumbnail(fileUri, modifiedTime); ++else ++ thumbnailFactory.save_thumbnail(thumbnailPixbuf, fileUri, modifiedTime); +diff --git a/extensions/desktop-icons/dbusUtils.js b/extensions/desktop-icons/dbusUtils.js +new file mode 100644 +index 00000000..19fe9878 +--- /dev/null ++++ b/extensions/desktop-icons/dbusUtils.js +@@ -0,0 +1,103 @@ ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++var NautilusFileOperationsProxy; ++var FreeDesktopFileManagerProxy; ++ ++const NautilusFileOperationsInterface = ` ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++`; ++ ++const NautilusFileOperationsProxyInterface = Gio.DBusProxy.makeProxyWrapper(NautilusFileOperationsInterface); ++ ++const FreeDesktopFileManagerInterface = ` ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++`; ++ ++const FreeDesktopFileManagerProxyInterface = Gio.DBusProxy.makeProxyWrapper(FreeDesktopFileManagerInterface); ++ ++function init() { ++ NautilusFileOperationsProxy = new NautilusFileOperationsProxyInterface( ++ Gio.DBus.session, ++ 'org.gnome.Nautilus', ++ '/org/gnome/Nautilus', ++ (proxy, error) => { ++ if (error) { ++ log('Error connecting to Nautilus'); ++ } ++ } ++ ); ++ ++ FreeDesktopFileManagerProxy = new FreeDesktopFileManagerProxyInterface( ++ Gio.DBus.session, ++ 'org.freedesktop.FileManager1', ++ '/org/freedesktop/FileManager1', ++ (proxy, error) => { ++ if (error) { ++ log('Error connecting to Nautilus'); ++ } ++ } ++ ); ++} ++ ++function openFileWithOtherApplication(filePath) { ++ let fdList = new Gio.UnixFDList(); ++ let channel = GLib.IOChannel.new_file(filePath, "r"); ++ fdList.append(channel.unix_get_fd()); ++ channel.set_close_on_unref(true); ++ let builder = GLib.VariantBuilder.new(GLib.VariantType.new("a{sv}")); ++ let options = builder.end(); ++ let parameters = GLib.Variant.new_tuple([GLib.Variant.new_string("0"), ++ GLib.Variant.new_handle(0), ++ options]); ++ Gio.bus_get(Gio.BusType.SESSION, null, ++ (source, result) => { ++ let dbus_connection = Gio.bus_get_finish(result); ++ dbus_connection.call_with_unix_fd_list("org.freedesktop.portal.Desktop", ++ "/org/freedesktop/portal/desktop", ++ "org.freedesktop.portal.OpenURI", ++ "OpenFile", ++ parameters, ++ GLib.VariantType.new("o"), ++ Gio.DBusCallFlags.NONE, ++ -1, ++ fdList, ++ null, ++ null); ++ } ++ ); ++} +diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js +new file mode 100644 +index 00000000..a2d1f127 +--- /dev/null ++++ b/extensions/desktop-icons/desktopGrid.js +@@ -0,0 +1,692 @@ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Gtk = imports.gi.Gtk; ++const Clutter = imports.gi.Clutter; ++const St = imports.gi.St; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Shell = imports.gi.Shell; ++ ++const Signals = imports.signals; ++ ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++const BoxPointer = imports.ui.boxpointer; ++const PopupMenu = imports.ui.popupMenu; ++const GrabHelper = imports.ui.grabHelper; ++const Config = imports.misc.config; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const CreateFolderDialog = Me.imports.createFolderDialog; ++const Extension = Me.imports.extension; ++const FileItem = Me.imports.fileItem; ++const Prefs = Me.imports.prefs; ++const DBusUtils = Me.imports.dbusUtils; ++const DesktopIconsUtil = Me.imports.desktopIconsUtil; ++const Util = imports.misc.util; ++ ++const Clipboard = St.Clipboard.get_default(); ++const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; ++const Gettext = imports.gettext.domain('desktop-icons'); ++ ++const _ = Gettext.gettext; ++ ++ ++/* From NautilusFileUndoManagerState */ ++var UndoStatus = { ++ NONE: 0, ++ UNDO: 1, ++ REDO: 2, ++}; ++ ++var StoredCoordinates = { ++ PRESERVE: 0, ++ OVERWRITE:1, ++ ASSIGN:2, ++}; ++ ++class Placeholder extends St.Bin { ++ constructor() { ++ super(); ++ } ++} ++ ++var DesktopGrid = class { ++ ++ constructor(bgManager) { ++ this._bgManager = bgManager; ++ ++ this._fileItemHandlers = new Map(); ++ this._fileItems = []; ++ ++ this.layout = new Clutter.GridLayout({ ++ orientation: Clutter.Orientation.VERTICAL, ++ column_homogeneous: true, ++ row_homogeneous: true ++ }); ++ ++ this._actorLayout = new Clutter.BinLayout({ ++ x_align: Clutter.BinAlignment.FIXED, ++ y_align: Clutter.BinAlignment.FIXED ++ }); ++ ++ this.actor = new St.Widget({ ++ layout_manager: this._actorLayout ++ }); ++ this.actor._delegate = this; ++ ++ this._grid = new St.Widget({ ++ name: 'DesktopGrid', ++ layout_manager: this.layout, ++ reactive: true, ++ x_expand: true, ++ y_expand: true, ++ can_focus: true, ++ opacity: 255 ++ }); ++ this.actor.add_child(this._grid); ++ ++ this._renamePopup = new RenamePopup(this); ++ this.actor.add_child(this._renamePopup.actor); ++ ++ this._bgManager._container.add_child(this.actor); ++ ++ this.actor.connect('destroy', () => this._onDestroy()); ++ ++ let monitorIndex = bgManager._monitorIndex; ++ this._monitorConstraint = new Layout.MonitorConstraint({ ++ index: monitorIndex, ++ work_area: true ++ }); ++ this.actor.add_constraint(this._monitorConstraint); ++ ++ this._addDesktopBackgroundMenu(); ++ ++ this._bgDestroyedId = bgManager.backgroundActor.connect('destroy', ++ () => this._backgroundDestroyed()); ++ ++ this._grid.connect('button-press-event', (actor, event) => this._onPressButton(actor, event)); ++ ++ this._grid.connect('key-press-event', this._onKeyPress.bind(this)); ++ ++ this._grid.connect('allocation-changed', () => Extension.desktopManager.scheduleReLayoutChildren()); ++ } ++ ++ _onKeyPress(actor, event) { ++ if (global.stage.get_key_focus() != actor) ++ return Clutter.EVENT_PROPAGATE; ++ ++ let symbol = event.get_key_symbol(); ++ let isCtrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0; ++ let isShift = (event.get_state() & Clutter.ModifierType.SHIFT_MASK) != 0; ++ if (isCtrl && isShift && [Clutter.Z, Clutter.z].indexOf(symbol) > -1) { ++ this._doRedo(); ++ return Clutter.EVENT_STOP; ++ } ++ else if (isCtrl && [Clutter.Z, Clutter.z].indexOf(symbol) > -1) { ++ this._doUndo(); ++ return Clutter.EVENT_STOP; ++ } ++ else if (isCtrl && [Clutter.C, Clutter.c].indexOf(symbol) > -1) { ++ Extension.desktopManager.doCopy(); ++ return Clutter.EVENT_STOP; ++ } ++ else if (isCtrl && [Clutter.X, Clutter.x].indexOf(symbol) > -1) { ++ Extension.desktopManager.doCut(); ++ return Clutter.EVENT_STOP; ++ } ++ else if (isCtrl && [Clutter.V, Clutter.v].indexOf(symbol) > -1) { ++ this._doPaste(); ++ return Clutter.EVENT_STOP; ++ } ++ else if (symbol == Clutter.Return) { ++ Extension.desktopManager.doOpen(); ++ return Clutter.EVENT_STOP; ++ } ++ else if (symbol == Clutter.Delete) { ++ Extension.desktopManager.doTrash(); ++ return Clutter.EVENT_STOP; ++ } else if (symbol == Clutter.F2) { ++ // Support renaming other grids file items. ++ Extension.desktopManager.doRename(); ++ return Clutter.EVENT_STOP; ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _backgroundDestroyed() { ++ this._bgDestroyedId = 0; ++ if (this._bgManager == null) ++ return; ++ ++ if (this._bgManager._backgroundSource) { ++ this._bgDestroyedId = this._bgManager.backgroundActor.connect('destroy', ++ () => this._backgroundDestroyed()); ++ } else { ++ this.actor.destroy(); ++ } ++ } ++ ++ _onDestroy() { ++ if (this._bgDestroyedId && this._bgManager.backgroundActor != null) ++ this._bgManager.backgroundActor.disconnect(this._bgDestroyedId); ++ this._bgDestroyedId = 0; ++ this._bgManager = null; ++ } ++ ++ _onNewFolderClicked() { ++ ++ let dialog = new CreateFolderDialog.CreateFolderDialog(); ++ ++ dialog.connect('response', (dialog, name) => { ++ let dir = DesktopIconsUtil.getDesktopDir().get_child(name); ++ DBusUtils.NautilusFileOperationsProxy.CreateFolderRemote(dir.get_uri(), ++ (result, error) => { ++ if (error) ++ throw new Error('Error creating new folder: ' + error.message); ++ } ++ ); ++ }); ++ ++ dialog.open(); ++ } ++ ++ _parseClipboardText(text) { ++ if (text === null) ++ return [false, false, null]; ++ ++ let lines = text.split('\n'); ++ let [mime, action, ...files] = lines; ++ ++ if (mime != 'x-special/nautilus-clipboard') ++ return [false, false, null]; ++ ++ if (!(['copy', 'cut'].includes(action))) ++ return [false, false, null]; ++ let isCut = action == 'cut'; ++ ++ /* Last line is empty due to the split */ ++ if (files.length <= 1) ++ return [false, false, null]; ++ /* Remove last line */ ++ files.pop(); ++ ++ return [true, isCut, files]; ++ } ++ ++ _doPaste() { ++ Clipboard.get_text(CLIPBOARD_TYPE, ++ (clipboard, text) => { ++ let [valid, is_cut, files] = this._parseClipboardText(text); ++ if (!valid) ++ return; ++ ++ let desktopDir = `${DesktopIconsUtil.getDesktopDir().get_uri()}`; ++ if (is_cut) { ++ DBusUtils.NautilusFileOperationsProxy.MoveURIsRemote(files, desktopDir, ++ (result, error) => { ++ if (error) ++ throw new Error('Error moving files: ' + error.message); ++ } ++ ); ++ } else { ++ DBusUtils.NautilusFileOperationsProxy.CopyURIsRemote(files, desktopDir, ++ (result, error) => { ++ if (error) ++ throw new Error('Error copying files: ' + error.message); ++ } ++ ); ++ } ++ } ++ ); ++ } ++ ++ _onPasteClicked() { ++ this._doPaste(); ++ } ++ ++ _doUndo() { ++ DBusUtils.NautilusFileOperationsProxy.UndoRemote( ++ (result, error) => { ++ if (error) ++ throw new Error('Error performing undo: ' + error.message); ++ } ++ ); ++ } ++ ++ _onUndoClicked() { ++ this._doUndo(); ++ } ++ ++ _doRedo() { ++ DBusUtils.NautilusFileOperationsProxy.RedoRemote( ++ (result, error) => { ++ if (error) ++ throw new Error('Error performing redo: ' + error.message); ++ } ++ ); ++ } ++ ++ _onRedoClicked() { ++ this._doRedo(); ++ } ++ ++ _onOpenDesktopInFilesClicked() { ++ Gio.AppInfo.launch_default_for_uri_async(DesktopIconsUtil.getDesktopDir().get_uri(), ++ null, null, ++ (source, result) => { ++ try { ++ Gio.AppInfo.launch_default_for_uri_finish(result); ++ } catch (e) { ++ log('Error opening Desktop in Files: ' + e.message); ++ } ++ } ++ ); ++ } ++ ++ _onOpenTerminalClicked() { ++ let desktopPath = DesktopIconsUtil.getDesktopDir().get_path(); ++ DesktopIconsUtil.launchTerminal(desktopPath); ++ } ++ ++ _syncUndoRedo() { ++ this._undoMenuItem.actor.visible = DBusUtils.NautilusFileOperationsProxy.UndoStatus == UndoStatus.UNDO; ++ this._redoMenuItem.actor.visible = DBusUtils.NautilusFileOperationsProxy.UndoStatus == UndoStatus.REDO; ++ } ++ ++ _undoStatusChanged(proxy, properties, test) { ++ if ('UndoStatus' in properties.deep_unpack()) ++ this._syncUndoRedo(); ++ } ++ ++ _createDesktopBackgroundMenu() { ++ let menu = new PopupMenu.PopupMenu(Main.layoutManager.dummyCursor, ++ 0, St.Side.TOP); ++ menu.addAction(_("New Folder"), () => this._onNewFolderClicked()); ++ menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this._pasteMenuItem = menu.addAction(_("Paste"), () => this._onPasteClicked()); ++ this._undoMenuItem = menu.addAction(_("Undo"), () => this._onUndoClicked()); ++ this._redoMenuItem = menu.addAction(_("Redo"), () => this._onRedoClicked()); ++ menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ menu.addAction(_("Show Desktop in Files"), () => this._onOpenDesktopInFilesClicked()); ++ menu.addAction(_("Open in Terminal"), () => this._onOpenTerminalClicked()); ++ menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ menu.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop'); ++ menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ menu.addSettingsAction(_("Display Settings"), 'gnome-display-panel.desktop'); ++ menu.addSettingsAction(_("Settings"), 'gnome-control-center.desktop'); ++ ++ menu.actor.add_style_class_name('background-menu'); ++ ++ Main.layoutManager.uiGroup.add_child(menu.actor); ++ menu.actor.hide(); ++ ++ menu._propertiesChangedId = DBusUtils.NautilusFileOperationsProxy.connect('g-properties-changed', ++ this._undoStatusChanged.bind(this)); ++ this._syncUndoRedo(); ++ ++ menu.connect('destroy', ++ () => DBusUtils.NautilusFileOperationsProxy.disconnect(menu._propertiesChangedId)); ++ menu.connect('open-state-changed', ++ (popupm, isOpen) => { ++ if (isOpen) { ++ Clipboard.get_text(CLIPBOARD_TYPE, ++ (clipBoard, text) => { ++ let [valid, is_cut, files] = this._parseClipboardText(text); ++ this._pasteMenuItem.setSensitive(valid); ++ } ++ ); ++ } ++ } ++ ); ++ this._pasteMenuItem.setSensitive(false); ++ ++ return menu; ++ } ++ ++ _openMenu(x, y) { ++ Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); ++ this.actor._desktopBackgroundMenu.open(BoxPointer.PopupAnimation.NONE); ++ /* Since the handler is in the press event it needs to ignore the release event ++ * to not immediately close the menu on release ++ */ ++ this.actor._desktopBackgroundManager.ignoreRelease(); ++ } ++ ++ _addFileItemTo(fileItem, column, row, coordinatesAction) { ++ let placeholder = this.layout.get_child_at(column, row); ++ placeholder.child = fileItem.actor; ++ this._fileItems.push(fileItem); ++ let selectedId = fileItem.connect('selected', this._onFileItemSelected.bind(this)); ++ let renameId = fileItem.connect('rename-clicked', this.doRename.bind(this)); ++ this._fileItemHandlers.set(fileItem, [selectedId, renameId]); ++ ++ /* If this file is new in the Desktop and hasn't yet ++ * fixed coordinates, store the new possition to ensure ++ * that the next time it will be shown in the same possition. ++ * Also store the new possition if it has been moved by the user, ++ * and not triggered by a screen change. ++ */ ++ if ((fileItem.savedCoordinates == null) || (coordinatesAction == StoredCoordinates.OVERWRITE)) { ++ let [fileX, fileY] = placeholder.get_transformed_position(); ++ fileItem.savedCoordinates = [Math.round(fileX), Math.round(fileY)]; ++ } ++ } ++ ++ addFileItemCloseTo(fileItem, x, y, coordinatesAction) { ++ let [column, row] = this._getEmptyPlaceClosestTo(x, y, coordinatesAction); ++ this._addFileItemTo(fileItem, column, row, coordinatesAction); ++ } ++ ++ _getEmptyPlaceClosestTo(x, y, coordinatesAction) { ++ let maxColumns = this._getMaxColumns(); ++ let maxRows = this._getMaxRows(); ++ ++ let [actorX, actorY] = this._grid.get_transformed_position(); ++ let actorWidth = this._grid.allocation.x2 - this._grid.allocation.x1; ++ let actorHeight = this._grid.allocation.y2 - this._grid.allocation.y1; ++ let placeX = Math.round((x - actorX) * maxColumns / actorWidth); ++ let placeY = Math.round((y - actorY) * maxRows / actorHeight); ++ ++ placeX = DesktopIconsUtil.clamp(placeX, 0, maxColumns - 1); ++ placeY = DesktopIconsUtil.clamp(placeY, 0, maxRows - 1); ++ if (this.layout.get_child_at(placeX, placeY).child == null) ++ return [placeX, placeY]; ++ let found = false; ++ let resColumn = null; ++ let resRow = null; ++ let minDistance = Infinity; ++ for (let column = 0; column < maxColumns; column++) { ++ for (let row = 0; row < maxRows; row++) { ++ let placeholder = this.layout.get_child_at(column, row); ++ if (placeholder.child != null) ++ continue; ++ ++ let [proposedX, proposedY] = placeholder.get_transformed_position(); ++ if (coordinatesAction == StoredCoordinates.ASSIGN) ++ return [column, row]; ++ let distance = DesktopIconsUtil.distanceBetweenPoints(proposedX, proposedY, x, y); ++ if (distance < minDistance) { ++ found = true; ++ minDistance = distance; ++ resColumn = column; ++ resRow = row; ++ } ++ } ++ } ++ ++ if (!found) ++ throw new Error(`Not enough place at monitor ${this._bgManager._monitorIndex}`); ++ ++ return [resColumn, resRow]; ++ } ++ ++ removeFileItem(fileItem) { ++ let index = this._fileItems.indexOf(fileItem); ++ if (index > -1) ++ this._fileItems.splice(index, 1); ++ else ++ throw new Error('Error removing children from container'); ++ ++ let [column, row] = this._getPosOfFileItem(fileItem); ++ let placeholder = this.layout.get_child_at(column, row); ++ placeholder.child = null; ++ let [selectedId, renameId] = this._fileItemHandlers.get(fileItem); ++ fileItem.disconnect(selectedId); ++ fileItem.disconnect(renameId); ++ this._fileItemHandlers.delete(fileItem); ++ } ++ ++ _fillPlaceholders() { ++ for (let column = 0; column < this._getMaxColumns(); column++) { ++ for (let row = 0; row < this._getMaxRows(); row++) { ++ this.layout.attach(new Placeholder(), column, row, 1, 1); ++ } ++ } ++ } ++ ++ reset() { ++ let tmpFileItemsCopy = this._fileItems.slice(); ++ for (let fileItem of tmpFileItemsCopy) ++ this.removeFileItem(fileItem); ++ this._grid.remove_all_children(); ++ ++ this._fillPlaceholders(); ++ } ++ ++ _onStageMotion(actor, event) { ++ if (this._drawingRubberBand) { ++ let [x, y] = event.get_coords(); ++ this._updateRubberBand(x, y); ++ this._selectFromRubberband(x, y); ++ } ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _onPressButton(actor, event) { ++ let button = event.get_button(); ++ let [x, y] = event.get_coords(); ++ ++ this._grid.grab_key_focus(); ++ ++ if (button == 1) { ++ let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK); ++ let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK); ++ if (!shiftPressed && !controlPressed) ++ Extension.desktopManager.clearSelection(); ++ let [gridX, gridY] = this._grid.get_transformed_position(); ++ Extension.desktopManager.startRubberBand(x, y, gridX, gridY); ++ return Clutter.EVENT_STOP; ++ } ++ ++ if (button == 3) { ++ this._openMenu(x, y); ++ ++ return Clutter.EVENT_STOP; ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _addDesktopBackgroundMenu() { ++ this.actor._desktopBackgroundMenu = this._createDesktopBackgroundMenu(); ++ this.actor._desktopBackgroundManager = new PopupMenu.PopupMenuManager({ actor: this.actor }); ++ this.actor._desktopBackgroundManager.addMenu(this.actor._desktopBackgroundMenu); ++ ++ this.actor.connect('destroy', () => { ++ this.actor._desktopBackgroundMenu.destroy(); ++ this.actor._desktopBackgroundMenu = null; ++ this.actor._desktopBackgroundManager = null; ++ }); ++ } ++ ++ _getMaxColumns() { ++ let gridWidth = this._grid.allocation.x2 - this._grid.allocation.x1; ++ return Math.floor(gridWidth / Prefs.get_desired_width(St.ThemeContext.get_for_stage(global.stage).scale_factor)); ++ } ++ ++ _getMaxRows() { ++ let gridHeight = this._grid.allocation.y2 - this._grid.allocation.y1; ++ return Math.floor(gridHeight / Prefs.get_desired_height(St.ThemeContext.get_for_stage(global.stage).scale_factor)); ++ } ++ ++ acceptDrop(source, actor, x, y, time) { ++ /* Coordinates are relative to the grid, we want to transform them to ++ * absolute coordinates to work across monitors */ ++ let [gridX, gridY] = this.actor.get_transformed_position(); ++ let [absoluteX, absoluteY] = [x + gridX, y + gridY]; ++ return Extension.desktopManager.acceptDrop(absoluteX, absoluteY); ++ } ++ ++ _getPosOfFileItem(itemToFind) { ++ if (itemToFind == null) ++ throw new Error('Error at _getPosOfFileItem: child cannot be null'); ++ ++ let found = false; ++ let maxColumns = this._getMaxColumns(); ++ let maxRows = this._getMaxRows(); ++ let column = 0; ++ let row = 0; ++ for (column = 0; column < maxColumns; column++) { ++ for (row = 0; row < maxRows; row++) { ++ let item = this.layout.get_child_at(column, row); ++ if (item.child && item.child._delegate.file.equal(itemToFind.file)) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (found) ++ break; ++ } ++ ++ if (!found) ++ throw new Error('Position of file item was not found'); ++ ++ return [column, row]; ++ } ++ ++ _onFileItemSelected(fileItem, keepCurrentSelection, addToSelection) { ++ this._grid.grab_key_focus(); ++ } ++ ++ doRename(fileItem) { ++ this._renamePopup.onFileItemRenameClicked(fileItem); ++ } ++}; ++ ++var RenamePopup = class { ++ ++ constructor(grid) { ++ this._source = null; ++ this._isOpen = false; ++ ++ this._renameEntry = new St.Entry({ hint_text: _("Enter file name…"), ++ can_focus: true, ++ x_expand: true }); ++ this._renameEntry.clutter_text.connect('activate', this._onRenameAccepted.bind(this)); ++ this._renameOkButton= new St.Button({ label: _("OK"), ++ style_class: 'app-view-control button', ++ button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, ++ reactive: true, ++ can_focus: true, ++ x_expand: true }); ++ this._renameCancelButton = new St.Button({ label: _("Cancel"), ++ style_class: 'app-view-control button', ++ button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, ++ reactive: true, ++ can_focus: true, ++ x_expand: true }); ++ this._renameCancelButton.connect('clicked', () => { this._onRenameCanceled(); }); ++ this._renameOkButton.connect('clicked', () => { this._onRenameAccepted(); }); ++ let renameButtonsBoxLayout = new Clutter.BoxLayout({ homogeneous: true }); ++ let renameButtonsBox = new St.Widget({ layout_manager: renameButtonsBoxLayout, ++ x_expand: true }); ++ renameButtonsBox.add_child(this._renameCancelButton); ++ renameButtonsBox.add_child(this._renameOkButton); ++ ++ let renameContentLayout = new Clutter.BoxLayout({ spacing: 6, ++ orientation: Clutter.Orientation.VERTICAL }); ++ let renameContent = new St.Widget({ style_class: 'rename-popup', ++ layout_manager: renameContentLayout, ++ x_expand: true }); ++ renameContent.add_child(this._renameEntry); ++ renameContent.add_child(renameButtonsBox); ++ ++ this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP, { can_focus: false, x_expand: false }); ++ this.actor = this._boxPointer.actor; ++ this.actor.style_class = 'popup-menu-boxpointer'; ++ this.actor.add_style_class_name('popup-menu'); ++ this.actor.visible = false; ++ this._boxPointer.bin.set_child(renameContent); ++ ++ this._grabHelper = new GrabHelper.GrabHelper(grid.actor, { actionMode: Shell.ActionMode.POPUP }); ++ this._grabHelper.addActor(this.actor); ++ } ++ ++ _popup() { ++ if (this._isOpen) ++ return; ++ ++ this._isOpen = this._grabHelper.grab({ actor: this.actor, ++ onUngrab: this._popdown.bind(this) }); ++ ++ if (!this._isOpen) { ++ this._grabHelper.ungrab({ actor: this.actor }); ++ return; ++ } ++ ++ this._boxPointer.setPosition(this._source.actor, 0.5); ++ if (ExtensionUtils.versionCheck(['3.28', '3.30'], Config.PACKAGE_VERSION)) ++ this._boxPointer.show(BoxPointer.PopupAnimation.FADE | ++ BoxPointer.PopupAnimation.SLIDE); ++ else ++ this._boxPointer.open(BoxPointer.PopupAnimation.FADE | ++ BoxPointer.PopupAnimation.SLIDE); ++ ++ this.emit('open-state-changed', true); ++ } ++ ++ _popdown() { ++ if (!this._isOpen) ++ return; ++ ++ this._grabHelper.ungrab({ actor: this.actor }); ++ ++ if (ExtensionUtils.versionCheck(['3.28', '3.30'], Config.PACKAGE_VERSION)) ++ this._boxPointer.hide(BoxPointer.PopupAnimation.FADE | ++ BoxPointer.PopupAnimation.SLIDE); ++ else ++ this._boxPointer.close(BoxPointer.PopupAnimation.FADE | ++ BoxPointer.PopupAnimation.SLIDE); ++ ++ this._isOpen = false; ++ this.emit('open-state-changed', false); ++ } ++ ++ onFileItemRenameClicked(fileItem) { ++ this._source = fileItem; ++ ++ this._renameEntry.text = fileItem.displayName; ++ ++ this._popup(); ++ this._renameEntry.grab_key_focus(); ++ this._renameEntry.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); ++ let extensionOffset = DesktopIconsUtil.getFileExtensionOffset(fileItem.displayName, fileItem.isDirectory); ++ this._renameEntry.clutter_text.set_selection(0, extensionOffset); ++ } ++ ++ _onRenameAccepted() { ++ this._popdown(); ++ DBusUtils.NautilusFileOperationsProxy.RenameFileRemote(this._source.file.get_uri(), ++ this._renameEntry.get_text(), ++ (result, error) => { ++ if (error) ++ throw new Error('Error renaming file: ' + error.message); ++ } ++ ); ++ } ++ ++ _onRenameCanceled() { ++ this._popdown(); ++ } ++}; ++Signals.addSignalMethods(RenamePopup.prototype); +diff --git a/extensions/desktop-icons/desktopIconsUtil.js b/extensions/desktop-icons/desktopIconsUtil.js +new file mode 100644 +index 00000000..0aea6542 +--- /dev/null ++++ b/extensions/desktop-icons/desktopIconsUtil.js +@@ -0,0 +1,123 @@ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Gtk = imports.gi.Gtk; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Prefs = Me.imports.prefs; ++ ++const TERMINAL_SCHEMA = 'org.gnome.desktop.default-applications.terminal'; ++const EXEC_KEY = 'exec'; ++ ++var DEFAULT_ATTRIBUTES = 'metadata::*,standard::*,access::*,time::modified,unix::mode'; ++ ++function getDesktopDir() { ++ let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP); ++ return Gio.File.new_for_commandline_arg(desktopPath); ++} ++ ++function clamp(value, min, max) { ++ return Math.max(Math.min(value, max), min); ++}; ++ ++function launchTerminal(workdir) { ++ let terminalSettings = new Gio.Settings({ schema_id: TERMINAL_SCHEMA }); ++ let exec = terminalSettings.get_string(EXEC_KEY); ++ let argv = [exec, `--working-directory=${workdir}`]; ++ ++ /* The following code has been extracted from GNOME Shell's ++ * source code in Misc.Util.trySpawn function and modified to ++ * set the working directory. ++ * ++ * https://gitlab.gnome.org/GNOME/gnome-shell/blob/gnome-3-30/js/misc/util.js ++ */ ++ ++ var success, pid; ++ try { ++ [success, pid] = GLib.spawn_async(workdir, argv, null, ++ GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, ++ null); ++ } catch (err) { ++ /* Rewrite the error in case of ENOENT */ ++ if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) { ++ throw new GLib.SpawnError({ code: GLib.SpawnError.NOENT, ++ message: _("Command not found") }); ++ } else if (err instanceof GLib.Error) { ++ // The exception from gjs contains an error string like: ++ // Error invoking GLib.spawn_command_line_async: Failed to ++ // execute child process "foo" (No such file or directory) ++ // We are only interested in the part in the parentheses. (And ++ // we can't pattern match the text, since it gets localized.) ++ let message = err.message.replace(/.*\((.+)\)/, '$1'); ++ throw new (err.constructor)({ code: err.code, ++ message: message }); ++ } else { ++ throw err; ++ } ++ } ++ // Dummy child watch; we don't want to double-fork internally ++ // because then we lose the parent-child relationship, which ++ // can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275 ++ GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, () => {}); ++} ++ ++function distanceBetweenPoints(x, y, x2, y2) { ++ return (Math.pow(x - x2, 2) + Math.pow(y - y2, 2)); ++} ++ ++function getExtraFolders() { ++ let extraFolders = new Array(); ++ if (Prefs.settings.get_boolean('show-home')) { ++ extraFolders.push([Gio.File.new_for_commandline_arg(GLib.get_home_dir()), Prefs.FileType.USER_DIRECTORY_HOME]); ++ } ++ if (Prefs.settings.get_boolean('show-trash')) { ++ extraFolders.push([Gio.File.new_for_uri('trash:///'), Prefs.FileType.USER_DIRECTORY_TRASH]); ++ } ++ return extraFolders; ++} ++ ++function getFileExtensionOffset(filename, isDirectory) { ++ let offset = filename.length; ++ ++ if (!isDirectory) { ++ let doubleExtensions = ['.gz', '.bz2', '.sit', '.Z', '.bz', '.xz']; ++ for (let extension of doubleExtensions) { ++ if (filename.endsWith(extension)) { ++ offset -= extension.length; ++ filename = filename.substring(0, offset); ++ break; ++ } ++ } ++ let lastDot = filename.lastIndexOf('.'); ++ if (lastDot > 0) ++ offset = lastDot; ++ } ++ return offset; ++} ++ ++function getGtkClassBackgroundColor(classname, state) { ++ let widget = new Gtk.WidgetPath(); ++ widget.append_type(Gtk.Widget); ++ ++ let context = new Gtk.StyleContext(); ++ context.set_path(widget); ++ context.add_class(classname); ++ return context.get_background_color(state); ++} +diff --git a/extensions/desktop-icons/desktopManager.js b/extensions/desktop-icons/desktopManager.js +new file mode 100644 +index 00000000..399aee03 +--- /dev/null ++++ b/extensions/desktop-icons/desktopManager.js +@@ -0,0 +1,754 @@ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Gtk = imports.gi.Gtk; ++const Clutter = imports.gi.Clutter; ++const GObject = imports.gi.GObject; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++const Meta = imports.gi.Meta; ++ ++const Animation = imports.ui.animation; ++const Background = imports.ui.background; ++const DND = imports.ui.dnd; ++const Main = imports.ui.main; ++const GrabHelper = imports.ui.grabHelper; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Extension = Me.imports.extension; ++const DesktopGrid = Me.imports.desktopGrid; ++const FileItem = Me.imports.fileItem; ++const Prefs = Me.imports.prefs; ++const DBusUtils = Me.imports.dbusUtils; ++const DesktopIconsUtil = Me.imports.desktopIconsUtil; ++ ++const Clipboard = St.Clipboard.get_default(); ++const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; ++ ++var S_IWOTH = 0x00002; ++ ++function getDpy() { ++ return global.screen || global.display; ++} ++ ++function findMonitorIndexForPos(x, y) { ++ return getDpy().get_monitor_index_for_rect(new Meta.Rectangle({x, y})); ++} ++ ++ ++var DesktopManager = GObject.registerClass({ ++ Properties: { ++ 'writable-by-others': GObject.ParamSpec.boolean( ++ 'writable-by-others', ++ 'WritableByOthers', ++ 'Whether the desktop\'s directory can be written by others (o+w unix permission)', ++ GObject.ParamFlags.READABLE, ++ false ++ ) ++ } ++}, class DesktopManager extends GObject.Object { ++ _init(params) { ++ super._init(params); ++ ++ this._layoutChildrenId = 0; ++ this._deleteChildrenId = 0; ++ this._monitorDesktopDir = null; ++ this._desktopMonitorCancellable = null; ++ this._desktopGrids = {}; ++ this._fileItemHandlers = new Map(); ++ this._fileItems = new Map(); ++ this._dragCancelled = false; ++ this._queryFileInfoCancellable = null; ++ this._unixMode = null; ++ this._writableByOthers = null; ++ ++ this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', () => this._recreateDesktopIcons()); ++ this._rubberBand = new St.Widget({ style_class: 'rubber-band' }); ++ this._rubberBand.hide(); ++ Main.layoutManager._backgroundGroup.add_child(this._rubberBand); ++ this._grabHelper = new GrabHelper.GrabHelper(global.stage); ++ ++ this._addDesktopIcons(); ++ this._monitorDesktopFolder(); ++ ++ this.settingsId = Prefs.settings.connect('changed', () => this._recreateDesktopIcons()); ++ this.gtkSettingsId = Prefs.gtkSettings.connect('changed', (obj, key) => { ++ if (key == 'show-hidden') ++ this._recreateDesktopIcons(); ++ }); ++ ++ this._selection = new Set(); ++ this._currentSelection = new Set(); ++ this._inDrag = false; ++ this._dragXStart = Number.POSITIVE_INFINITY; ++ this._dragYStart = Number.POSITIVE_INFINITY; ++ } ++ ++ startRubberBand(x, y) { ++ this._rubberBandInitialX = x; ++ this._rubberBandInitialY = y; ++ this._initRubberBandColor(); ++ this._updateRubberBand(x, y); ++ this._rubberBand.show(); ++ this._grabHelper.grab({ actor: global.stage }); ++ Extension.lockActivitiesButton = true; ++ this._stageReleaseEventId = global.stage.connect('button-release-event', (actor, event) => { ++ this.endRubberBand(); ++ }); ++ this._rubberBandId = global.stage.connect('motion-event', (actor, event) => { ++ /* In some cases, when the user starts a rubberband selection and ends it ++ * (by releasing the left button) over a window instead of doing it over ++ * the desktop, the stage doesn't receive the "button-release" event. ++ * This happens currently with, at least, Dash to Dock extension, but ++ * it probably also happens with other applications or extensions. ++ * To fix this, we also end the rubberband selection if we detect mouse ++ * motion in the stage without the left button pressed during a ++ * rubberband selection. ++ * */ ++ let button = event.get_state(); ++ if (!(button & Clutter.ModifierType.BUTTON1_MASK)) { ++ this.endRubberBand(); ++ return; ++ } ++ [x, y] = event.get_coords(); ++ this._updateRubberBand(x, y); ++ let x0, y0, x1, y1; ++ if (x >= this._rubberBandInitialX) { ++ x0 = this._rubberBandInitialX; ++ x1 = x; ++ } else { ++ x1 = this._rubberBandInitialX; ++ x0 = x; ++ } ++ if (y >= this._rubberBandInitialY) { ++ y0 = this._rubberBandInitialY; ++ y1 = y; ++ } else { ++ y1 = this._rubberBandInitialY; ++ y0 = y; ++ } ++ for (let [fileUri, fileItem] of this._fileItems) { ++ fileItem.emit('selected', true, true, ++ fileItem.intersectsWith(x0, y0, x1 - x0, y1 - y0)); ++ } ++ }); ++ } ++ ++ endRubberBand() { ++ this._rubberBand.hide(); ++ Extension.lockActivitiesButton = false; ++ this._grabHelper.ungrab(); ++ global.stage.disconnect(this._rubberBandId); ++ global.stage.disconnect(this._stageReleaseEventId); ++ this._rubberBandId = 0; ++ this._stageReleaseEventId = 0; ++ ++ this._selection = new Set([...this._selection, ...this._currentSelection]); ++ this._currentSelection.clear(); ++ } ++ ++ _updateRubberBand(currentX, currentY) { ++ let x = this._rubberBandInitialX < currentX ? this._rubberBandInitialX ++ : currentX; ++ let y = this._rubberBandInitialY < currentY ? this._rubberBandInitialY ++ : currentY; ++ let width = Math.abs(this._rubberBandInitialX - currentX); ++ let height = Math.abs(this._rubberBandInitialY - currentY); ++ /* TODO: Convert to gobject.set for 3.30 */ ++ this._rubberBand.set_position(x, y); ++ this._rubberBand.set_size(width, height); ++ } ++ ++ _recreateDesktopIcons() { ++ this._destroyDesktopIcons(); ++ this._addDesktopIcons(); ++ } ++ ++ _addDesktopIcons() { ++ forEachBackgroundManager(bgManager => { ++ let newGrid = new DesktopGrid.DesktopGrid(bgManager); ++ newGrid.actor.connect('destroy', (actor) => { ++ // if a grid loses its actor, remove it from the grid list ++ for (let grid in this._desktopGrids) ++ if (this._desktopGrids[grid].actor == actor) { ++ delete this._desktopGrids[grid]; ++ break; ++ } ++ }); ++ this._desktopGrids[bgManager._monitorIndex] = newGrid; ++ }); ++ ++ this._scanFiles(); ++ } ++ ++ _destroyDesktopIcons() { ++ Object.values(this._desktopGrids).forEach(grid => grid.actor.destroy()); ++ this._desktopGrids = {}; ++ } ++ ++ /** ++ * Initialize rubberband color from the GTK rubberband class ++ * */ ++ _initRubberBandColor() { ++ let rgba = DesktopIconsUtil.getGtkClassBackgroundColor('rubberband', Gtk.StateFlags.NORMAL); ++ let background_color = ++ 'rgba(' + rgba.red * 255 + ', ' + rgba.green * 255 + ', ' + rgba.blue * 255 + ', 0.4)'; ++ this._rubberBand.set_style('background-color: ' + background_color); ++ } ++ ++ async _scanFiles() { ++ for (let [fileItem, id] of this._fileItemHandlers) ++ fileItem.disconnect(id); ++ this._fileItemHandlers = new Map(); ++ ++ if (!this._unixMode) { ++ let desktopDir = DesktopIconsUtil.getDesktopDir(); ++ let fileInfo = desktopDir.query_info(Gio.FILE_ATTRIBUTE_UNIX_MODE, ++ Gio.FileQueryInfoFlags.NONE, ++ null); ++ this._unixMode = fileInfo.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE); ++ this._setWritableByOthers((this._unixMode & S_IWOTH) != 0); ++ } ++ ++ try { ++ let tmpFileItems = new Map(); ++ for (let [file, info, extra] of await this._enumerateDesktop()) { ++ let fileItem = new FileItem.FileItem(file, info, extra); ++ tmpFileItems.set(fileItem.file.get_uri(), fileItem); ++ let id = fileItem.connect('selected', ++ this._onFileItemSelected.bind(this)); ++ ++ this._fileItemHandlers.set(fileItem, id); ++ } ++ this._fileItems = tmpFileItems; ++ } catch (e) { ++ if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) ++ log(`Error loading desktop files ${e.message}`); ++ return; ++ } ++ ++ this.scheduleReLayoutChildren(); ++ } ++ ++ getDesktopFileNames () { ++ let fileList = []; ++ for (let [uri, item] of this._fileItems) { ++ fileList.push(item.fileName); ++ } ++ return fileList; ++ } ++ ++ _enumerateDesktop() { ++ return new Promise((resolve, reject) => { ++ if (this._desktopEnumerateCancellable) ++ this._desktopEnumerateCancellable.cancel(); ++ ++ this._desktopEnumerateCancellable = new Gio.Cancellable(); ++ ++ let desktopDir = DesktopIconsUtil.getDesktopDir(); ++ desktopDir.enumerate_children_async(DesktopIconsUtil.DEFAULT_ATTRIBUTES, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_DEFAULT, ++ this._desktopEnumerateCancellable, ++ (source, result) => { ++ try { ++ let fileEnum = source.enumerate_children_finish(result); ++ let resultGenerator = function *() { ++ let info; ++ for (let [newFolder, extras] of DesktopIconsUtil.getExtraFolders()) { ++ yield [newFolder, newFolder.query_info(DesktopIconsUtil.DEFAULT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, this._desktopEnumerateCancellable), extras]; ++ } ++ while ((info = fileEnum.next_file(null))) ++ yield [fileEnum.get_child(info), info, Prefs.FileType.NONE]; ++ }.bind(this); ++ resolve(resultGenerator()); ++ } catch (e) { ++ reject(e); ++ } ++ }); ++ }); ++ } ++ ++ _monitorDesktopFolder() { ++ if (this._monitorDesktopDir) { ++ this._monitorDesktopDir.cancel(); ++ this._monitorDesktopDir = null; ++ } ++ ++ let desktopDir = DesktopIconsUtil.getDesktopDir(); ++ this._monitorDesktopDir = desktopDir.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null); ++ this._monitorDesktopDir.set_rate_limit(1000); ++ this._monitorDesktopDir.connect('changed', (obj, file, otherFile, eventType) => this._updateDesktopIfChanged(file, otherFile, eventType)); ++ } ++ ++ checkIfSpecialFilesAreSelected() { ++ for (let fileItem of this._selection) { ++ if (fileItem.isSpecial) ++ return true; ++ } ++ return false; ++ } ++ ++ getNumberOfSelectedItems() { ++ return this._selection.size; ++ } ++ ++ get writableByOthers() { ++ return this._writableByOthers; ++ } ++ ++ _setWritableByOthers(value) { ++ if (value == this._writableByOthers) ++ return; ++ ++ this._writableByOthers = value ++ this.notify('writable-by-others'); ++ } ++ ++ _updateDesktopIfChanged (file, otherFile, eventType) { ++ let { ++ DELETED, MOVED_IN, MOVED_OUT, CREATED, RENAMED, CHANGES_DONE_HINT, ATTRIBUTE_CHANGED ++ } = Gio.FileMonitorEvent; ++ ++ let fileUri = file.get_uri(); ++ let fileItem = null; ++ if (this._fileItems.has(fileUri)) ++ fileItem = this._fileItems.get(fileUri); ++ switch(eventType) { ++ case RENAMED: ++ this._fileItems.delete(fileUri); ++ this._fileItems.set(otherFile.get_uri(), fileItem); ++ fileItem.onFileRenamed(otherFile); ++ return; ++ case CHANGES_DONE_HINT: ++ case ATTRIBUTE_CHANGED: ++ /* a file changed, rather than the desktop itself */ ++ let desktopDir = DesktopIconsUtil.getDesktopDir(); ++ if (file.get_uri() != desktopDir.get_uri()) { ++ fileItem.onAttributeChanged(); ++ return; ++ } ++ ++ if (this._queryFileInfoCancellable) ++ this._queryFileInfoCancellable.cancel(); ++ ++ file.query_info_async(Gio.FILE_ATTRIBUTE_UNIX_MODE, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_DEFAULT, ++ this._queryFileInfoCancellable, ++ (source, result) => { ++ try { ++ let info = source.query_info_finish(result); ++ this._queryFileInfoCancellable = null; ++ ++ this._unixMode = info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE); ++ this._setWritableByOthers((this._unixMode & S_IWOTH) != 0); ++ ++ if (this._writableByOthers) ++ log(`desktop-icons: Desktop is writable by others - will not allow launching any desktop files`); ++ } catch(error) { ++ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) ++ global.log('Error getting desktop unix mode: ' + error); ++ } ++ }); ++ ++ return; ++ } ++ ++ // Only get a subset of events we are interested in. ++ // Note that CREATED will emit a CHANGES_DONE_HINT ++ if (![DELETED, MOVED_IN, MOVED_OUT, CREATED].includes(eventType)) ++ return; ++ ++ this._recreateDesktopIcons(); ++ } ++ ++ _setupDnD() { ++ this._draggableContainer = new St.Widget({ ++ visible: true, ++ width: 1, ++ height: 1, ++ x: 0, ++ y: 0, ++ style_class: 'draggable' ++ }); ++ this._draggableContainer._delegate = this; ++ this._draggable = DND.makeDraggable(this._draggableContainer, ++ { ++ manualMode: true, ++ dragActorOpacity: 100 ++ }); ++ ++ this._draggable.connect('drag-cancelled', () => this._onDragCancelled()); ++ this._draggable.connect('drag-end', () => this._onDragEnd()); ++ ++ this._draggable._dragActorDropped = event => this._dragActorDropped(event); ++ } ++ ++ dragStart() { ++ if (this._inDrag) { ++ return; ++ } ++ ++ this._setupDnD(); ++ let event = Clutter.get_current_event(); ++ let [x, y] = event.get_coords(); ++ [this._dragXStart, this._dragYStart] = event.get_coords(); ++ this._inDrag = true; ++ ++ for (let fileItem of this._selection) { ++ let clone = new Clutter.Clone({ ++ source: fileItem.actor, ++ reactive: false ++ }); ++ clone.x = fileItem.actor.get_transformed_position()[0]; ++ clone.y = fileItem.actor.get_transformed_position()[1]; ++ this._draggableContainer.add_child(clone); ++ } ++ ++ Main.layoutManager.uiGroup.add_child(this._draggableContainer); ++ this._draggable.startDrag(x, y, global.get_current_time(), event.get_event_sequence()); ++ } ++ ++ _onDragCancelled() { ++ let event = Clutter.get_current_event(); ++ let [x, y] = event.get_coords(); ++ this._dragCancelled = true; ++ } ++ ++ _onDragEnd() { ++ this._inDrag = false; ++ Main.layoutManager.uiGroup.remove_child(this._draggableContainer); ++ } ++ ++ _dragActorDropped(event) { ++ let [dropX, dropY] = event.get_coords(); ++ let target = this._draggable._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL, ++ dropX, dropY); ++ ++ // We call observers only once per motion with the innermost ++ // target actor. If necessary, the observer can walk the ++ // parent itself. ++ let dropEvent = { ++ dropActor: this._draggable._dragActor, ++ targetActor: target, ++ clutterEvent: event ++ }; ++ for (let dragMonitor of DND.dragMonitors) { ++ let dropFunc = dragMonitor.dragDrop; ++ if (dropFunc) ++ switch (dropFunc(dropEvent)) { ++ case DragDropResult.FAILURE: ++ case DragDropResult.SUCCESS: ++ return true; ++ case DragDropResult.CONTINUE: ++ continue; ++ } ++ } ++ ++ // At this point it is too late to cancel a drag by destroying ++ // the actor, the fate of which is decided by acceptDrop and its ++ // side-effects ++ this._draggable._dragCancellable = false; ++ ++ let destroyActor = false; ++ while (target) { ++ if (target._delegate && target._delegate.acceptDrop) { ++ let [r, targX, targY] = target.transform_stage_point(dropX, dropY); ++ if (target._delegate.acceptDrop(this._draggable.actor._delegate, ++ this._draggable._dragActor, ++ targX, ++ targY, ++ event.get_time())) { ++ // If it accepted the drop without taking the actor, ++ // handle it ourselves. ++ if (this._draggable._dragActor.get_parent() == Main.uiGroup) { ++ if (this._draggable._restoreOnSuccess) { ++ this._draggable._restoreDragActor(event.get_time()); ++ return true; ++ } ++ else { ++ // We need this in order to make sure drag-end is fired ++ destroyActor = true; ++ } ++ } ++ ++ this._draggable._dragInProgress = false; ++ getDpy().set_cursor(Meta.Cursor.DEFAULT); ++ this._draggable.emit('drag-end', event.get_time(), true); ++ if (destroyActor) { ++ this._draggable._dragActor.destroy(); ++ } ++ this._draggable._dragComplete(); ++ ++ return true; ++ } ++ } ++ target = target.get_parent(); ++ } ++ ++ this._draggable._cancelDrag(event.get_time()); ++ ++ return true; ++ } ++ ++ acceptDrop(xEnd, yEnd) { ++ let savedCoordinates = new Map(); ++ let [xDiff, yDiff] = [xEnd - this._dragXStart, yEnd - this._dragYStart]; ++ /* Remove all items before dropping new ones, so we can freely reposition ++ * them. ++ */ ++ for (let item of this._selection) { ++ let [itemX, itemY] = item.actor.get_transformed_position(); ++ let monitorIndex = findMonitorIndexForPos(itemX, itemY); ++ savedCoordinates.set(item, [itemX, itemY]); ++ this._desktopGrids[monitorIndex].removeFileItem(item); ++ } ++ ++ for (let item of this._selection) { ++ let [itemX, itemY] = savedCoordinates.get(item); ++ /* Set the new ideal position where the item drop should happen */ ++ let newFileX = Math.round(xDiff + itemX); ++ let newFileY = Math.round(yDiff + itemY); ++ let monitorIndex = findMonitorIndexForPos(newFileX, newFileY); ++ this._desktopGrids[monitorIndex].addFileItemCloseTo(item, newFileX, newFileY, DesktopGrid.StoredCoordinates.OVERWRITE); ++ } ++ ++ return true; ++ } ++ ++ selectionDropOnFileItem (fileItemDestination) { ++ if (!fileItemDestination.isDirectory) ++ return false; ++ ++ let droppedUris = []; ++ for (let fileItem of this._selection) { ++ if (fileItem.isSpecial) ++ return false; ++ if (fileItemDestination.file.get_uri() == fileItem.file.get_uri()) ++ return false; ++ droppedUris.push(fileItem.file.get_uri()); ++ } ++ ++ if (droppedUris.length == 0) ++ return true; ++ ++ DBusUtils.NautilusFileOperationsProxy.MoveURIsRemote(droppedUris, ++ fileItemDestination.file.get_uri(), ++ (result, error) => { ++ if (error) ++ throw new Error('Error moving files: ' + error.message); ++ } ++ ); ++ for (let fileItem of this._selection) { ++ fileItem.state = FileItem.State.GONE; ++ } ++ ++ this._recreateDesktopIcons(); ++ ++ return true; ++ } ++ ++ _resetGridsAndScheduleLayout() { ++ this._deleteChildrenId = 0; ++ ++ Object.values(this._desktopGrids).forEach((grid) => grid.reset()); ++ ++ this._layoutChildrenId = GLib.idle_add(GLib.PRIORITY_LOW, () => this._layoutChildren()); ++ ++ return GLib.SOURCE_REMOVE; ++ } ++ ++ scheduleReLayoutChildren() { ++ if (this._deleteChildrenId != 0) ++ return; ++ ++ if (this._layoutChildrenId != 0) { ++ GLib.source_remove(this._layoutChildrenId); ++ this._layoutChildrenId = 0; ++ } ++ ++ ++ this._deleteChildrenId = GLib.idle_add(GLib.PRIORITY_LOW, () => this._resetGridsAndScheduleLayout()); ++ } ++ ++ _addFileItemCloseTo(item) { ++ let coordinates; ++ let x = 0; ++ let y = 0; ++ let coordinatesAction = DesktopGrid.StoredCoordinates.ASSIGN; ++ if (item.savedCoordinates != null) { ++ [x, y] = item.savedCoordinates; ++ coordinatesAction = DesktopGrid.StoredCoordinates.PRESERVE; ++ } ++ let monitorIndex = findMonitorIndexForPos(x, y); ++ let desktopGrid = this._desktopGrids[monitorIndex]; ++ try { ++ desktopGrid.addFileItemCloseTo(item, x, y, coordinatesAction); ++ } catch (e) { ++ log(`Error adding children to desktop: ${e.message}`); ++ } ++ } ++ ++ _layoutChildren() { ++ let showHidden = Prefs.gtkSettings.get_boolean('show-hidden'); ++ /* ++ * Paint the icons in two passes: ++ * * first pass paints those that have their coordinates defined in the metadata ++ * * second pass paints those new files that still don't have their definitive coordinates ++ */ ++ for (let [fileUri, fileItem] of this._fileItems) { ++ if (fileItem.savedCoordinates == null) ++ continue; ++ if (fileItem.state != FileItem.State.NORMAL) ++ continue; ++ if (!showHidden && fileItem.isHidden) ++ continue; ++ this._addFileItemCloseTo(fileItem); ++ } ++ ++ for (let [fileUri, fileItem] of this._fileItems) { ++ if (fileItem.savedCoordinates !== null) ++ continue; ++ if (fileItem.state != FileItem.State.NORMAL) ++ continue; ++ if (!showHidden && fileItem.isHidden) ++ continue; ++ this._addFileItemCloseTo(fileItem); ++ } ++ ++ this._layoutChildrenId = 0; ++ return GLib.SOURCE_REMOVE; ++ } ++ ++ doRename() { ++ if (this._selection.size != 1) ++ return; ++ ++ let item = [...this._selection][0]; ++ if (item.canRename()) ++ item.doRename(); ++ } ++ ++ doOpen() { ++ for (let fileItem of this._selection) ++ fileItem.doOpen(); ++ } ++ ++ doTrash() { ++ DBusUtils.NautilusFileOperationsProxy.TrashFilesRemote([...this._selection].map((x) => { return x.file.get_uri(); }), ++ (source, error) => { ++ if (error) ++ throw new Error('Error trashing files on the desktop: ' + error.message); ++ } ++ ); ++ } ++ ++ doEmptyTrash() { ++ DBusUtils.NautilusFileOperationsProxy.EmptyTrashRemote( (source, error) => { ++ if (error) ++ throw new Error('Error trashing files on the desktop: ' + error.message); ++ }); ++ } ++ ++ _onFileItemSelected(fileItem, keepCurrentSelection, rubberBandSelection, addToSelection) { ++ ++ if (!keepCurrentSelection && !this._inDrag) ++ this.clearSelection(); ++ ++ let selection = keepCurrentSelection && rubberBandSelection ? this._currentSelection : this._selection; ++ if (addToSelection) ++ selection.add(fileItem); ++ else ++ selection.delete(fileItem); ++ ++ for (let [fileUri, fileItem] of this._fileItems) ++ fileItem.isSelected = this._currentSelection.has(fileItem) || this._selection.has(fileItem); ++ } ++ ++ clearSelection() { ++ for (let [fileUri, fileItem] of this._fileItems) ++ fileItem.isSelected = false; ++ this._selection = new Set(); ++ this._currentSelection = new Set(); ++ } ++ ++ _getClipboardText(isCopy) { ++ let action = isCopy ? 'copy' : 'cut'; ++ let text = `x-special/nautilus-clipboard\n${action}\n${ ++ [...this._selection].map(s => s.file.get_uri()).join('\n') ++ }\n`; ++ ++ return text; ++ } ++ ++ doCopy() { ++ Clipboard.set_text(CLIPBOARD_TYPE, this._getClipboardText(true)); ++ } ++ ++ doCut() { ++ Clipboard.set_text(CLIPBOARD_TYPE, this._getClipboardText(false)); ++ } ++ ++ destroy() { ++ if (this._monitorDesktopDir) ++ this._monitorDesktopDir.cancel(); ++ this._monitorDesktopDir = null; ++ ++ if (this.settingsId) ++ Prefs.settings.disconnect(this.settingsId); ++ this.settingsId = 0; ++ if (this.gtkSettingsId) ++ Prefs.gtkSettings.disconnect(this.gtkSettingsId); ++ this.gtkSettingsId = 0; ++ ++ if (this._layoutChildrenId) ++ GLib.source_remove(this._layoutChildrenId); ++ this._layoutChildrenId = 0; ++ ++ if (this._deleteChildrenId) ++ GLib.source_remove(this._deleteChildrenId); ++ this._deleteChildrenId = 0; ++ ++ if (this._monitorsChangedId) ++ Main.layoutManager.disconnect(this._monitorsChangedId); ++ this._monitorsChangedId = 0; ++ if (this._stageReleaseEventId) ++ global.stage.disconnect(this._stageReleaseEventId); ++ this._stageReleaseEventId = 0; ++ ++ if (this._rubberBandId) ++ global.stage.disconnect(this._rubberBandId); ++ this._rubberBandId = 0; ++ ++ this._rubberBand.destroy(); ++ ++ if (this._queryFileInfoCancellable) ++ this._queryFileInfoCancellable.cancel(); ++ ++ Object.values(this._desktopGrids).forEach(grid => grid.actor.destroy()); ++ this._desktopGrids = {} ++ } ++}); ++ ++function forEachBackgroundManager(func) { ++ Main.layoutManager._bgManagers.forEach(func); ++} +diff --git a/extensions/desktop-icons/extension.js b/extensions/desktop-icons/extension.js +new file mode 100644 +index 00000000..4b960aba +--- /dev/null ++++ b/extensions/desktop-icons/extension.js +@@ -0,0 +1,71 @@ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Main = imports.ui.main; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Prefs = Me.imports.prefs; ++const { DesktopManager } = Me.imports.desktopManager; ++const DBusUtils = Me.imports.dbusUtils; ++ ++var desktopManager = null; ++var addBackgroundMenuOrig = null; ++var _startupPreparedId; ++var lockActivitiesButton = false; ++ ++var oldShouldToggleByCornerOrButtonFunction = null; ++ ++function init() { ++ addBackgroundMenuOrig = Main.layoutManager._addBackgroundMenu; ++ ++ Prefs.initTranslations(); ++} ++ ++function newShouldToggleByCornerOrButton() { ++ if (lockActivitiesButton) ++ return false; ++ else ++ return oldShouldToggleByCornerOrButtonFunction.bind(Main.overview); ++} ++ ++function enable() { ++ // register a new function to allow to lock the Activities button when doing a rubberband selection ++ oldShouldToggleByCornerOrButtonFunction = Main.overview.shouldToggleByCornerOrButton; ++ Main.overview.shouldToggleByCornerOrButton = newShouldToggleByCornerOrButton; ++ // wait until the startup process has ended ++ if (Main.layoutManager._startingUp) ++ _startupPreparedId = Main.layoutManager.connect('startup-complete', () => innerEnable(true)); ++ else ++ innerEnable(false); ++} ++ ++function innerEnable(disconnectSignal) { ++ if (disconnectSignal) ++ Main.layoutManager.disconnect(_startupPreparedId); ++ DBusUtils.init(); ++ Prefs.init(); ++ Main.layoutManager._addBackgroundMenu = function() {}; ++ desktopManager = new DesktopManager(); ++} ++ ++function disable() { ++ desktopManager.destroy(); ++ Main.layoutManager._addBackgroundMenu = addBackgroundMenuOrig; ++ Main.overview.shouldToggleByCornerOrButton = oldShouldToggleByCornerOrButtonFunction; ++} +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +new file mode 100644 +index 00000000..0c6a54d7 +--- /dev/null ++++ b/extensions/desktop-icons/fileItem.js +@@ -0,0 +1,830 @@ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Gtk = imports.gi.Gtk; ++const Clutter = imports.gi.Clutter; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const St = imports.gi.St; ++const Pango = imports.gi.Pango; ++const Meta = imports.gi.Meta; ++const GdkPixbuf = imports.gi.GdkPixbuf; ++const Cogl = imports.gi.Cogl; ++const GnomeDesktop = imports.gi.GnomeDesktop; ++ ++const Mainloop = imports.mainloop; ++const Signals = imports.signals; ++ ++const Background = imports.ui.background; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const Util = imports.misc.util; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Extension = Me.imports.extension; ++const Prefs = Me.imports.prefs; ++const DBusUtils = Me.imports.dbusUtils; ++const DesktopIconsUtil = Me.imports.desktopIconsUtil; ++ ++const Gettext = imports.gettext.domain('desktop-icons'); ++ ++const _ = Gettext.gettext; ++ ++const DRAG_TRESHOLD = 8; ++ ++var S_IXUSR = 0o00100; ++var S_IWOTH = 0o00002; ++ ++var State = { ++ NORMAL: 0, ++ GONE: 1, ++}; ++ ++var FileItem = class { ++ ++ constructor(file, fileInfo, fileExtra) { ++ this._fileExtra = fileExtra; ++ this._loadThumbnailDataCancellable = null; ++ this._thumbnailScriptWatch = 0; ++ this._setMetadataCancellable = null; ++ this._queryFileInfoCancellable = null; ++ this._isSpecial = this._fileExtra != Prefs.FileType.NONE; ++ ++ this._file = file; ++ ++ this._savedCoordinates = null; ++ let savedCoordinates = fileInfo.get_attribute_as_string('metadata::nautilus-icon-position'); ++ if (savedCoordinates != null) ++ this._savedCoordinates = savedCoordinates.split(',').map(x => Number(x)); ++ ++ this._state = State.NORMAL; ++ ++ this.actor = new St.Bin({ visible: true }); ++ this.actor.set_fill(true, true); ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ this.actor.set_height(Prefs.get_desired_height(scaleFactor)); ++ this.actor.set_width(Prefs.get_desired_width(scaleFactor)); ++ this.actor._delegate = this; ++ this.actor.connect('destroy', () => this._onDestroy()); ++ ++ this._container = new St.BoxLayout({ reactive: true, ++ track_hover: true, ++ can_focus: true, ++ style_class: 'file-item', ++ x_expand: true, ++ y_expand: true, ++ x_align: Clutter.ActorAlign.FILL, ++ vertical: true }); ++ this.actor.set_child(this._container); ++ this._icon = new St.Bin(); ++ this._icon.set_height(Prefs.get_icon_size() * scaleFactor); ++ ++ this._iconContainer = new St.Bin({ visible: true }); ++ this._iconContainer.child = this._icon; ++ this._container.add_child(this._iconContainer); ++ ++ this._label = new St.Label({ ++ style_class: 'name-label' ++ }); ++ ++ this._container.add_child(this._label); ++ let clutterText = this._label.get_clutter_text(); ++ /* TODO: Convert to gobject.set for 3.30 */ ++ clutterText.set_line_wrap(true); ++ clutterText.set_line_wrap_mode(Pango.WrapMode.WORD_CHAR); ++ clutterText.set_ellipsize(Pango.EllipsizeMode.END); ++ ++ this._container.connect('button-press-event', (actor, event) => this._onPressButton(actor, event)); ++ this._container.connect('motion-event', (actor, event) => this._onMotion(actor, event)); ++ this._container.connect('leave-event', (actor, event) => this._onLeave(actor, event)); ++ this._container.connect('button-release-event', (actor, event) => this._onReleaseButton(actor, event)); ++ ++ /* Set the metadata and update relevant UI */ ++ this._updateMetadataFromFileInfo(fileInfo); ++ ++ this._menuManager = null; ++ this._menu = null; ++ this._updateIcon(); ++ ++ this._isSelected = false; ++ this._primaryButtonPressed = false; ++ if (this._attributeCanExecute && !this._isValidDesktopFile) ++ this._execLine = this.file.get_path(); ++ if (fileExtra == Prefs.FileType.USER_DIRECTORY_TRASH) { ++ // if this icon is the trash, monitor the state of the directory to update the icon ++ this._trashChanged = false; ++ this._queryTrashInfoCancellable = null; ++ this._scheduleTrashRefreshId = 0; ++ this._monitorTrashDir = this._file.monitor_directory(Gio.FileMonitorFlags.WATCH_MOVES, null); ++ this._monitorTrashId = this._monitorTrashDir.connect('changed', (obj, file, otherFile, eventType) => { ++ switch(eventType) { ++ case Gio.FileMonitorEvent.DELETED: ++ case Gio.FileMonitorEvent.MOVED_OUT: ++ case Gio.FileMonitorEvent.CREATED: ++ case Gio.FileMonitorEvent.MOVED_IN: ++ if (this._queryTrashInfoCancellable || this._scheduleTrashRefreshId) { ++ if (this._scheduleTrashRefreshId) ++ GLib.source_remove(this._scheduleTrashRefreshId); ++ this._scheduleTrashRefreshId = Mainloop.timeout_add(200, () => this._refreshTrashIcon()); ++ } else { ++ this._refreshTrashIcon(); ++ } ++ break; ++ } ++ }); ++ } ++ ++ this._writebleByOthersId = Extension.desktopManager.connect('notify::writable-by-others', () => { ++ if (!this._isValidDesktopFile) ++ return; ++ this._refreshMetadataAsync(true); ++ }); ++ } ++ ++ onAttributeChanged() { ++ if (this._isDesktopFile) { ++ this._refreshMetadataAsync(true); ++ } ++ } ++ ++ _onDestroy() { ++ /* Regular file data */ ++ if (this._setMetadataCancellable) ++ this._setMetadataCancellable.cancel(); ++ if (this._queryFileInfoCancellable) ++ this._queryFileInfoCancellable.cancel(); ++ ++ Extension.desktopManager.disconnect(this._writebleByOthersId); ++ ++ /* Thumbnailing */ ++ if (this._thumbnailScriptWatch) ++ GLib.source_remove(this._thumbnailScriptWatch); ++ if (this._loadThumbnailDataCancellable) ++ this._loadThumbnailDataCancellable.cancel(); ++ ++ /* Desktop file */ ++ if (this._monitorDesktopFileId) { ++ this._monitorDesktopFile.disconnect(this._monitorDesktopFileId); ++ this._monitorDesktopFile.cancel(); ++ } ++ ++ /* Trash */ ++ if (this._monitorTrashDir) { ++ this._monitorTrashDir.disconnect(this._monitorTrashId); ++ this._monitorTrashDir.cancel(); ++ } ++ if (this._queryTrashInfoCancellable) ++ this._queryTrashInfoCancellable.cancel(); ++ if (this._scheduleTrashRefreshId) ++ GLib.source_remove(this._scheduleTrashRefreshId); ++ ++ /* Menu */ ++ this._removeMenu(); ++ } ++ ++ _refreshMetadataAsync(rebuild) { ++ if (this._queryFileInfoCancellable) ++ this._queryFileInfoCancellable.cancel(); ++ this._queryFileInfoCancellable = new Gio.Cancellable(); ++ this._file.query_info_async(DesktopIconsUtil.DEFAULT_ATTRIBUTES, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_DEFAULT, ++ this._queryFileInfoCancellable, ++ (source, result) => { ++ try { ++ let newFileInfo = source.query_info_finish(result); ++ this._queryFileInfoCancellable = null; ++ this._updateMetadataFromFileInfo(newFileInfo); ++ if (rebuild) { ++ this._recreateMenu(); ++ this._updateIcon(); ++ } ++ } catch(error) { ++ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) ++ global.log("Error getting the file info: " + error); ++ } ++ }); ++ } ++ ++ _updateMetadataFromFileInfo(fileInfo) { ++ this._fileInfo = fileInfo; ++ ++ let oldLabelText = this._label.text; ++ ++ this._displayName = fileInfo.get_attribute_as_string('standard::display-name'); ++ this._attributeCanExecute = fileInfo.get_attribute_boolean('access::can-execute'); ++ this._unixmode = fileInfo.get_attribute_uint32('unix::mode') ++ this._writableByOthers = (this._unixmode & S_IWOTH) != 0; ++ this._trusted = fileInfo.get_attribute_as_string('metadata::trusted') == 'true'; ++ this._attributeContentType = fileInfo.get_content_type(); ++ this._isDesktopFile = this._attributeContentType == 'application/x-desktop'; ++ ++ if (this._isDesktopFile && this._writableByOthers) ++ log(`desktop-icons: File ${this._displayName} is writable by others - will not allow launching`); ++ ++ if (this._isDesktopFile) { ++ this._desktopFile = Gio.DesktopAppInfo.new_from_filename(this._file.get_path()); ++ if (!this._desktopFile) { ++ log(`Couldn’t parse ${this._displayName} as a desktop file, will treat it as a regular file.`); ++ this._isValidDesktopFile = false; ++ } else { ++ this._isValidDesktopFile = true; ++ } ++ } else { ++ this._isValidDesktopFile = false; ++ } ++ ++ if (this.displayName != oldLabelText) { ++ this._label.text = this.displayName; ++ } ++ ++ this._fileType = fileInfo.get_file_type(); ++ this._isDirectory = this._fileType == Gio.FileType.DIRECTORY; ++ this._isSpecial = this._fileExtra != Prefs.FileType.NONE; ++ this._isHidden = fileInfo.get_is_hidden() | fileInfo.get_is_backup(); ++ this._isSymlink = fileInfo.get_is_symlink(); ++ this._modifiedTime = this._fileInfo.get_attribute_uint64("time::modified"); ++ /* ++ * This is a glib trick to detect broken symlinks. If a file is a symlink, the filetype ++ * points to the final file, unless it is broken; thus if the file type is SYMBOLIC_LINK, ++ * it must be a broken link. ++ * https://developer.gnome.org/gio/stable/GFile.html#g-file-query-info ++ */ ++ this._isBrokenSymlink = this._isSymlink && this._fileType == Gio.FileType.SYMBOLIC_LINK ++ } ++ ++ onFileRenamed(file) { ++ this._file = file; ++ this._refreshMetadataAsync(false); ++ } ++ ++ _updateIcon() { ++ if (this._fileExtra == Prefs.FileType.USER_DIRECTORY_TRASH) { ++ this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null); ++ return; ++ } ++ ++ let thumbnailFactory = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE); ++ if (thumbnailFactory.can_thumbnail(this._file.get_uri(), ++ this._attributeContentType, ++ this._modifiedTime)) { ++ let thumbnail = thumbnailFactory.lookup(this._file.get_uri(), this._modifiedTime); ++ if (thumbnail == null) { ++ if (!thumbnailFactory.has_valid_failed_thumbnail(this._file.get_uri(), ++ this._modifiedTime)) { ++ let argv = []; ++ argv.push(GLib.build_filenamev([ExtensionUtils.getCurrentExtension().path, ++ 'createThumbnail.js'])); ++ argv.push(this._file.get_path()); ++ let [success, pid] = GLib.spawn_async(null, argv, null, ++ GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, null); ++ if (this._thumbnailScriptWatch) ++ GLib.source_remove(this._thumbnailScriptWatch); ++ this._thumbnailScriptWatch = GLib.child_watch_add(GLib.PRIORITY_DEFAULT, ++ pid, ++ (pid, exitCode) => { ++ this._thumbnailScriptWatch = 0; ++ if (exitCode == 0) ++ this._updateIcon(); ++ else ++ global.log('Failed to generate thumbnail for ' + this._filePath); ++ GLib.spawn_close_pid(pid); ++ return false; ++ } ++ ); ++ } ++ } else { ++ if (this._loadThumbnailDataCancellable) ++ this._loadThumbnailDataCancellable.cancel(); ++ this._loadThumbnailDataCancellable = new Gio.Cancellable(); ++ let thumbnailFile = Gio.File.new_for_path(thumbnail); ++ thumbnailFile.load_bytes_async(this._loadThumbnailDataCancellable, ++ (source, result) => { ++ try { ++ this._loadThumbnailDataCancellable = null; ++ let [thumbnailData, etag_out] = source.load_bytes_finish(result); ++ let thumbnailStream = Gio.MemoryInputStream.new_from_bytes(thumbnailData); ++ let thumbnailPixbuf = GdkPixbuf.Pixbuf.new_from_stream(thumbnailStream, null); ++ ++ if (thumbnailPixbuf != null) { ++ let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; ++ let thumbnailImage = new Clutter.Image(); ++ thumbnailImage.set_data(thumbnailPixbuf.get_pixels(), ++ thumbnailPixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888, ++ thumbnailPixbuf.width, ++ thumbnailPixbuf.height, ++ thumbnailPixbuf.rowstride ++ ); ++ let icon = new Clutter.Actor(); ++ icon.set_content(thumbnailImage); ++ let width = Prefs.get_desired_width(scaleFactor); ++ let height = Prefs.get_icon_size() * scaleFactor; ++ let aspectRatio = thumbnailPixbuf.width / thumbnailPixbuf.height; ++ if ((width / height) > aspectRatio) ++ icon.set_size(height * aspectRatio, height); ++ else ++ icon.set_size(width, width / aspectRatio); ++ this._icon.child = icon; ++ } ++ } catch (error) { ++ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { ++ global.log('Error while loading thumbnail: ' + error); ++ this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null); ++ } ++ } ++ } ++ ); ++ } ++ } ++ ++ if (this._isBrokenSymlink) { ++ this._icon.child = this._createEmblemedStIcon(null, 'text-x-generic'); ++ } else { ++ if (this.trustedDesktopFile && this._desktopFile.has_key('Icon')) ++ this._icon.child = this._createEmblemedStIcon(null, this._desktopFile.get_string('Icon')); ++ else ++ this._icon.child = this._createEmblemedStIcon(this._fileInfo.get_icon(), null); ++ } ++ } ++ ++ _refreshTrashIcon() { ++ if (this._queryTrashInfoCancellable) ++ this._queryTrashInfoCancellable.cancel(); ++ this._queryTrashInfoCancellable = new Gio.Cancellable(); ++ ++ this._file.query_info_async(DesktopIconsUtil.DEFAULT_ATTRIBUTES, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_DEFAULT, ++ this._queryTrashInfoCancellable, ++ (source, result) => { ++ try { ++ this._fileInfo = source.query_info_finish(result); ++ this._queryTrashInfoCancellable = null; ++ this._updateIcon(); ++ } catch(error) { ++ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) ++ global.log('Error getting the number of files in the trash: ' + error); ++ } ++ }); ++ ++ this._scheduleTrashRefreshId = 0; ++ return false; ++ } ++ ++ get file() { ++ return this._file; ++ } ++ ++ get isHidden() { ++ return this._isHidden; ++ } ++ ++ _createEmblemedStIcon(icon, iconName) { ++ if (icon == null) { ++ if (GLib.path_is_absolute(iconName)) { ++ let iconFile = Gio.File.new_for_commandline_arg(iconName); ++ icon = new Gio.FileIcon({ file: iconFile }); ++ } else { ++ icon = Gio.ThemedIcon.new_with_default_fallbacks(iconName); ++ } ++ } ++ let itemIcon = Gio.EmblemedIcon.new(icon, null); ++ ++ if (this._isSymlink) { ++ if (this._isBrokenSymlink) ++ itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-unreadable'))); ++ else ++ itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-symbolic-link'))); ++ } else if (this.trustedDesktopFile) { ++ itemIcon.add_emblem(Gio.Emblem.new(Gio.ThemedIcon.new('emblem-symbolic-link'))); ++ } ++ ++ return new St.Icon({ gicon: itemIcon, ++ icon_size: Prefs.get_icon_size() ++ }); ++ } ++ ++ doRename() { ++ if (!this.canRename()) { ++ log (`Error: ${this.file.get_uri()} cannot be renamed`); ++ return; ++ } ++ ++ this.emit('rename-clicked'); ++ } ++ ++ doOpen() { ++ if (this._isBrokenSymlink) { ++ log(`Error: Can’t open ${this.file.get_uri()} because it is a broken symlink.`); ++ return; ++ } ++ ++ if (this.trustedDesktopFile) { ++ this._desktopFile.launch_uris_as_manager([], null, GLib.SpawnFlags.SEARCH_PATH, null, null); ++ return; ++ } ++ ++ if (this._attributeCanExecute && !this._isDirectory && !this._isValidDesktopFile) { ++ if (this._execLine) ++ Util.spawnCommandLine(this._execLine); ++ return; ++ } ++ ++ Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(), ++ null, null, ++ (source, result) => { ++ try { ++ Gio.AppInfo.launch_default_for_uri_finish(result); ++ } catch (e) { ++ log('Error opening file ' + this.file.get_uri() + ': ' + e.message); ++ } ++ } ++ ); ++ } ++ ++ _onCopyClicked() { ++ Extension.desktopManager.doCopy(); ++ } ++ ++ _onCutClicked() { ++ Extension.desktopManager.doCut(); ++ } ++ ++ _onShowInFilesClicked() { ++ ++ DBusUtils.FreeDesktopFileManagerProxy.ShowItemsRemote([this.file.get_uri()], '', ++ (result, error) => { ++ if (error) ++ log('Error showing file on desktop: ' + error.message); ++ } ++ ); ++ } ++ ++ _onPropertiesClicked() { ++ ++ DBusUtils.FreeDesktopFileManagerProxy.ShowItemPropertiesRemote([this.file.get_uri()], '', ++ (result, error) => { ++ if (error) ++ log('Error showing properties: ' + error.message); ++ } ++ ); ++ } ++ ++ _onMoveToTrashClicked() { ++ Extension.desktopManager.doTrash(); ++ } ++ ++ _onEmptyTrashClicked() { ++ Extension.desktopManager.doEmptyTrash(); ++ } ++ ++ get _allowLaunchingText() { ++ if (this.trustedDesktopFile) ++ return _("Don’t Allow Launching"); ++ ++ return _("Allow Launching"); ++ } ++ ++ get metadataTrusted() { ++ return this._trusted; ++ } ++ ++ set metadataTrusted(value) { ++ this._trusted = value; ++ ++ let info = new Gio.FileInfo(); ++ info.set_attribute_string('metadata::trusted', ++ value ? 'true' : 'false'); ++ this._file.set_attributes_async(info, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_LOW, ++ null, ++ (source, result) => { ++ try { ++ source.set_attributes_finish(result); ++ this._refreshMetadataAsync(true); ++ } catch(e) { ++ log(`Failed to set metadata::trusted: ${e.message}`); ++ } ++ }); ++ } ++ ++ _onAllowDisallowLaunchingClicked() { ++ this.metadataTrusted = !this.trustedDesktopFile; ++ ++ /* ++ * we're marking as trusted, make the file executable too. note that we ++ * do not ever remove the executable bit, since we don't know who set ++ * it. ++ */ ++ if (this.metadataTrusted && !this._attributeCanExecute) { ++ let info = new Gio.FileInfo(); ++ let newUnixMode = this._unixmode | S_IXUSR; ++ info.set_attribute_uint32(Gio.FILE_ATTRIBUTE_UNIX_MODE, newUnixMode); ++ this._file.set_attributes_async(info, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_LOW, ++ null, ++ (source, result) => { ++ try { ++ source.set_attributes_finish (result); ++ } catch(e) { ++ log(`Failed to set unix mode: ${e.message}`); ++ } ++ }); ++ } ++ } ++ ++ canRename() { ++ return !this.trustedDesktopFile && this._fileExtra == Prefs.FileType.NONE; ++ } ++ ++ _doOpenWith() { ++ DBusUtils.openFileWithOtherApplication(this.file.get_path()); ++ } ++ ++ _getSelectionStyle() { ++ let rgba = DesktopIconsUtil.getGtkClassBackgroundColor('view', Gtk.StateFlags.SELECTED); ++ let background_color = ++ 'rgba(' + rgba.red * 255 + ', ' + rgba.green * 255 + ', ' + rgba.blue * 255 + ', 0.6)'; ++ let border_color = ++ 'rgba(' + rgba.red * 255 + ', ' + rgba.green * 255 + ', ' + rgba.blue * 255 + ', 0.8)'; ++ ++ return 'background-color: ' + background_color + ';' + ++ 'border-color: ' + border_color + ';' ++ } ++ ++ _removeMenu() { ++ if (this._menu != null) { ++ if (this._menuManager != null) ++ this._menuManager.removeMenu(this._menu); ++ ++ Main.layoutManager.uiGroup.remove_child(this._menu.actor); ++ this._menu.destroy(); ++ this._menu = null; ++ } ++ ++ this._menuManager = null; ++ } ++ ++ _recreateMenu() { ++ this._removeMenu(); ++ ++ this._menuManager = new PopupMenu.PopupMenuManager({ actor: this.actor }); ++ let side = St.Side.LEFT; ++ if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) ++ side = St.Side.RIGHT; ++ this._menu = new PopupMenu.PopupMenu(this.actor, 0.5, side); ++ this._menu.addAction(_('Open'), () => this.doOpen()); ++ switch (this._fileExtra) { ++ case Prefs.FileType.NONE: ++ if (!this._isDirectory) ++ this._actionOpenWith = this._menu.addAction(_('Open With Other Application'), () => this._doOpenWith()); ++ else ++ this._actionOpenWith = null; ++ this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this._actionCut = this._menu.addAction(_('Cut'), () => this._onCutClicked()); ++ this._actionCopy = this._menu.addAction(_('Copy'), () => this._onCopyClicked()); ++ if (this.canRename()) ++ this._menu.addAction(_('Rename…'), () => this.doRename()); ++ this._actionTrash = this._menu.addAction(_('Move to Trash'), () => this._onMoveToTrashClicked()); ++ if (this._isValidDesktopFile && !Extension.desktopManager.writableByOthers && !this._writableByOthers) { ++ this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this._allowLaunchingMenuItem = this._menu.addAction(this._allowLaunchingText, ++ () => this._onAllowDisallowLaunchingClicked()); ++ ++ } ++ break; ++ case Prefs.FileType.USER_DIRECTORY_TRASH: ++ this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this._menu.addAction(_('Empty Trash'), () => this._onEmptyTrashClicked()); ++ break; ++ default: ++ break; ++ } ++ this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this._menu.addAction(_('Properties'), () => this._onPropertiesClicked()); ++ this._menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this._menu.addAction(_('Show in Files'), () => this._onShowInFilesClicked()); ++ if (this._isDirectory && this.file.get_path() != null) ++ this._actionOpenInTerminal = this._menu.addAction(_('Open in Terminal'), () => this._onOpenTerminalClicked()); ++ ++ this._menuManager.addMenu(this._menu); ++ ++ Main.layoutManager.uiGroup.add_child(this._menu.actor); ++ this._menu.actor.hide(); ++ } ++ ++ _ensureMenu() { ++ if (this._menu == null) ++ this._recreateMenu(); ++ ++ return this._menu; ++ } ++ ++ _onOpenTerminalClicked () { ++ DesktopIconsUtil.launchTerminal(this.file.get_path()); ++ } ++ ++ _onPressButton(actor, event) { ++ let button = event.get_button(); ++ if (button == 3) { ++ if (!this.isSelected) ++ this.emit('selected', false, false, true); ++ this._ensureMenu().toggle(); ++ if (this._actionOpenWith) { ++ let allowOpenWith = (Extension.desktopManager.getNumberOfSelectedItems() == 1); ++ this._actionOpenWith.setSensitive(allowOpenWith); ++ } ++ let specialFilesSelected = Extension.desktopManager.checkIfSpecialFilesAreSelected(); ++ if (this._actionCut) ++ this._actionCut.setSensitive(!specialFilesSelected); ++ if (this._actionCopy) ++ this._actionCopy.setSensitive(!specialFilesSelected); ++ if (this._actionTrash) ++ this._actionTrash.setSensitive(!specialFilesSelected); ++ return Clutter.EVENT_STOP; ++ } else if (button == 1) { ++ if (event.get_click_count() == 1) { ++ let [x, y] = event.get_coords(); ++ this._primaryButtonPressed = true; ++ this._buttonPressInitialX = x; ++ this._buttonPressInitialY = y; ++ let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK); ++ let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK); ++ if (!this.isSelected) { ++ this.emit('selected', shiftPressed || controlPressed, false, true); ++ } ++ } ++ return Clutter.EVENT_STOP; ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _onLeave(actor, event) { ++ this._primaryButtonPressed = false; ++ } ++ ++ _onMotion(actor, event) { ++ let [x, y] = event.get_coords(); ++ if (this._primaryButtonPressed) { ++ let xDiff = x - this._buttonPressInitialX; ++ let yDiff = y - this._buttonPressInitialY; ++ let distance = Math.sqrt(Math.pow(xDiff, 2) + Math.pow(yDiff, 2)); ++ if (distance > DRAG_TRESHOLD) { ++ // Don't need to track anymore this if we start drag, and also ++ // avoids reentrance here ++ this._primaryButtonPressed = false; ++ let event = Clutter.get_current_event(); ++ let [x, y] = event.get_coords(); ++ Extension.desktopManager.dragStart(); ++ } ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _onReleaseButton(actor, event) { ++ let button = event.get_button(); ++ if (button == 1) { ++ // primaryButtonPressed is TRUE only if the user has pressed the button ++ // over an icon, and if (s)he has not started a drag&drop operation ++ if (this._primaryButtonPressed) { ++ this._primaryButtonPressed = false; ++ let shiftPressed = !!(event.get_state() & Clutter.ModifierType.SHIFT_MASK); ++ let controlPressed = !!(event.get_state() & Clutter.ModifierType.CONTROL_MASK); ++ if ((event.get_click_count() == 1) && Prefs.CLICK_POLICY_SINGLE && !shiftPressed && !controlPressed) ++ this.doOpen(); ++ this.emit('selected', shiftPressed || controlPressed, false, true); ++ return Clutter.EVENT_STOP; ++ } ++ if ((event.get_click_count() == 2) && (!Prefs.CLICK_POLICY_SINGLE)) ++ this.doOpen(); ++ } ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ get savedCoordinates() { ++ return this._savedCoordinates; ++ } ++ ++ _onSetMetadataFileFinished(source, result) { ++ try { ++ let [success, info] = source.set_attributes_finish(result); ++ } catch (error) { ++ if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) ++ log('Error setting metadata to desktop files ', error); ++ } ++ } ++ ++ set savedCoordinates(pos) { ++ if (this._setMetadataCancellable) ++ this._setMetadataCancellable.cancel(); ++ ++ this._setMetadataCancellable = new Gio.Cancellable(); ++ this._savedCoordinates = [pos[0], pos[1]]; ++ let info = new Gio.FileInfo(); ++ info.set_attribute_string('metadata::nautilus-icon-position', ++ `${pos[0]},${pos[1]}`); ++ this.file.set_attributes_async(info, ++ Gio.FileQueryInfoFlags.NONE, ++ GLib.PRIORITY_DEFAULT, ++ this._setMetadataCancellable, ++ (source, result) => { ++ this._setMetadataCancellable = null; ++ this._onSetMetadataFileFinished(source, result); ++ } ++ ); ++ } ++ ++ intersectsWith(argX, argY, argWidth, argHeight) { ++ let rect = new Meta.Rectangle({ x: argX, y: argY, width: argWidth, height: argHeight }); ++ let [containerX, containerY] = this._container.get_transformed_position(); ++ let boundingBox = new Meta.Rectangle({ x: containerX, ++ y: containerY, ++ width: this._container.allocation.x2 - this._container.allocation.x1, ++ height: this._container.allocation.y2 - this._container.allocation.y1 }); ++ let [intersects, _] = rect.intersect(boundingBox); ++ ++ return intersects; ++ } ++ ++ set isSelected(isSelected) { ++ isSelected = !!isSelected; ++ if (isSelected == this._isSelected) ++ return; ++ ++ if (isSelected) { ++ this._container.set_style(this._getSelectionStyle()); ++ } else { ++ this._container.set_style('background-color: transparent'); ++ this._container.set_style('border-color: transparent'); ++ } ++ ++ this._isSelected = isSelected; ++ } ++ ++ get isSelected() { ++ return this._isSelected; ++ } ++ ++ get isSpecial() { ++ return this._isSpecial; ++ } ++ ++ get state() { ++ return this._state; ++ } ++ ++ set state(state) { ++ if (state == this._state) ++ return; ++ ++ this._state = state; ++ } ++ ++ get isDirectory() { ++ return this._isDirectory; ++ } ++ ++ get trustedDesktopFile() { ++ return this._isValidDesktopFile && ++ this._attributeCanExecute && ++ this.metadataTrusted && ++ !Extension.desktopManager.writableByOthers && ++ !this._writableByOthers; ++ } ++ ++ get fileName() { ++ return this._fileInfo.get_name(); ++ } ++ ++ get displayName() { ++ if (this.trustedDesktopFile) ++ return this._desktopFile.get_name(); ++ ++ return this._displayName || null; ++ } ++ ++ acceptDrop() { ++ return Extension.desktopManager.selectionDropOnFileItem(this); ++ } ++}; ++Signals.addSignalMethods(FileItem.prototype); +diff --git a/extensions/desktop-icons/meson.build b/extensions/desktop-icons/meson.build +new file mode 100644 +index 00000000..8431af62 +--- /dev/null ++++ b/extensions/desktop-icons/meson.build +@@ -0,0 +1,19 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_schemas += files(join_paths('schemas', metadata_conf.get('gschemaname') + '.gschema.xml')) ++ ++extension_sources += files( ++ 'createFolderDialog.js', ++ 'createThumbnail.js', ++ 'dbusUtils.js', ++ 'desktopGrid.js', ++ 'desktopIconsUtil.js', ++ 'desktopManager.js', ++ 'extension.js', ++ 'fileItem.js', ++ 'prefs.js' ++) +diff --git a/extensions/desktop-icons/metadata.json.in b/extensions/desktop-icons/metadata.json.in +new file mode 100644 +index 00000000..78cabf08 +--- /dev/null ++++ b/extensions/desktop-icons/metadata.json.in +@@ -0,0 +1,11 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Desktop Icons", ++"description": "Provide desktop icons support for classic mode", ++"original-authors": [ "csoriano@redhat.com" ], ++"shell-version": [ "@shell_current@" ], ++"url": "@url@" ++} +diff --git a/extensions/desktop-icons/po/LINGUAS b/extensions/desktop-icons/po/LINGUAS +new file mode 100644 +index 00000000..65b7521d +--- /dev/null ++++ b/extensions/desktop-icons/po/LINGUAS +@@ -0,0 +1,19 @@ ++cs ++da ++de ++es ++fi ++fr ++fur ++hr ++hu ++id ++it ++ja ++nl ++pl ++pt_BR ++ru ++sv ++tr ++zh_TW +diff --git a/extensions/desktop-icons/po/POTFILES.in b/extensions/desktop-icons/po/POTFILES.in +new file mode 100644 +index 00000000..7c2ebd3b +--- /dev/null ++++ b/extensions/desktop-icons/po/POTFILES.in +@@ -0,0 +1,4 @@ ++prefs.js ++desktopGrid.js ++fileItem.js ++schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml +\ No newline at end of file +diff --git a/extensions/desktop-icons/po/cs.po b/extensions/desktop-icons/po/cs.po +new file mode 100644 +index 00000000..f5f9db43 +--- /dev/null ++++ b/extensions/desktop-icons/po/cs.po +@@ -0,0 +1,195 @@ ++# Czech translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Marek Černocký , 2018. ++# Milan Zink , 2018. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:49+0000\n" ++"PO-Revision-Date: 2019-03-02 18:02+0100\n" ++"Last-Translator: Daniel Rusek \n" ++"Language-Team: Czech \n" ++"Language: cs\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Název nové složky" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Vytvořit" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Zrušit" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Názvy složek nesmí obsahovat „/“." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Složka se nemůže jmenovat „.“." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Složka se nemůže jmenovat „..“." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Složky s „.“ na začátku jejich názvu jsou skryty." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Soubor nebo složka s tímto názvem již existuje." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Velikost ikon na pracovní ploše" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "malé" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "standardní" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "velké" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Zobrazovat osobní složku na pracovní ploše" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Zobrazovat ikonu koše na pracovní ploše" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nová složka" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Vložit" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Zpět" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Znovu" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Zobrazit plochu v Souborech" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Otevřít v terminálu" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Změnit pozadí…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Zobrazit nastavení" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Nastavení" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Zadejte název souboru…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Budiž" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Nepovolit spouštění" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Povolit spouštění" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Otevřít" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Otevřít pomocí jiné aplikace" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Vyjmout" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopírovat" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Přejmenovat…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Přesunout do koše" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Vyprázdnit koš" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Vlastnosti" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Zobrazit v Souborech" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Velikost ikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Nastavit velikost pro ikony na pracovní ploše." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Zobrazovat osobní složku" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Zobrazovat osobní složku na pracovní ploše." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Zobrazovat koš" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Zobrazovat ikonu koše na pracovní ploše." ++ ++#~ msgid "Huge" ++#~ msgstr "obrovské" ++ ++#~ msgid "Ok" ++#~ msgstr "Ok" +diff --git a/extensions/desktop-icons/po/da.po b/extensions/desktop-icons/po/da.po +new file mode 100644 +index 00000000..d3f51f06 +--- /dev/null ++++ b/extensions/desktop-icons/po/da.po +@@ -0,0 +1,159 @@ ++# Danish translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Alan Mortensen , 2018. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-01-15 10:59+0000\n" ++"PO-Revision-Date: 2019-02-09 11:35+0100\n" ++"Last-Translator: Alan Mortensen \n" ++"Language-Team: Danish \n" ++"Language: da\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.0.6\n" ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Størrelsen på skrivebordsikoner" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Små" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Store" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Vis den personlige mappe på skrivebordet" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Vis papirkurvsikonet på skrivebordet" ++ ++#: desktopGrid.js:187 desktopGrid.js:306 ++msgid "New Folder" ++msgstr "Ny mappe" ++ ++#: desktopGrid.js:308 ++msgid "Paste" ++msgstr "Indsæt" ++ ++#: desktopGrid.js:309 ++msgid "Undo" ++msgstr "Fortryd" ++ ++#: desktopGrid.js:310 ++msgid "Redo" ++msgstr "Omgør" ++ ++#: desktopGrid.js:312 ++msgid "Show Desktop in Files" ++msgstr "Vis skrivebordet i Filer" ++ ++#: desktopGrid.js:313 fileItem.js:586 ++msgid "Open in Terminal" ++msgstr "Åbn i terminal" ++ ++#: desktopGrid.js:315 ++msgid "Change Background…" ++msgstr "Skift baggrund …" ++ ++#: desktopGrid.js:317 ++msgid "Display Settings" ++msgstr "Skærmindstillinger" ++ ++#: desktopGrid.js:318 ++msgid "Settings" ++msgstr "Indstillinger" ++ ++#: desktopGrid.js:559 ++msgid "Enter file name…" ++msgstr "Indtast filnavn …" ++ ++#: desktopGrid.js:563 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopGrid.js:569 ++msgid "Cancel" ++msgstr "Annullér" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Tillad ikke opstart" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Tillad opstart" ++ ++#: fileItem.js:559 ++msgid "Open" ++msgstr "Åbn" ++ ++#: fileItem.js:562 ++msgid "Cut" ++msgstr "Klip" ++ ++#: fileItem.js:563 ++msgid "Copy" ++msgstr "Kopiér" ++ ++#: fileItem.js:565 ++msgid "Rename…" ++msgstr "Omdøb …" ++ ++#: fileItem.js:566 ++msgid "Move to Trash" ++msgstr "Flyt til papirkurven" ++ ++#: fileItem.js:576 ++msgid "Empty Trash" ++msgstr "Tøm papirkurven" ++ ++#: fileItem.js:582 ++msgid "Properties" ++msgstr "Egenskaber" ++ ++#: fileItem.js:584 ++msgid "Show in Files" ++msgstr "Vis i Filer" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ikonstørrelse" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Angiv størrelsen på skrivebordsikoner." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Vis personlig mappe" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Vis den personlige mappe på skrivebordet." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Vis papirkurvsikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Vis papirkurvsikonet på skrivebordet." ++ ++#~ msgid "Huge" ++#~ msgstr "Enorme" +diff --git a/extensions/desktop-icons/po/de.po b/extensions/desktop-icons/po/de.po +new file mode 100644 +index 00000000..ed5a2573 +--- /dev/null ++++ b/extensions/desktop-icons/po/de.po +@@ -0,0 +1,192 @@ ++# German translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Mario Blättermann , 2018. ++# rugk , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-07 22:46+0000\n" ++"PO-Revision-Date: 2019-03-09 15:42+0100\n" ++"Last-Translator: Tim Sabsch \n" ++"Language-Team: German \n" ++"Language: de\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Neuer Ordner" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Erstellen" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Abbrechen" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Ordnernamen dürfen kein »/« enthalten." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Ein Ordner darf nicht ».« genannt werden." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Ein Ordner darf nicht »..« genannt werden." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Ordner mit ».« am Anfang sind verborgen." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Es gibt bereits eine Datei oder einen Ordner mit diesem Namen." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Größe der Arbeitsflächensymbole" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Klein" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Groß" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Den persönlichen Ordner auf der Arbeitsfläche anzeigen" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Papierkorb-Symbol auf der Arbeitsfläche anzeigen" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Neuer Ordner" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Einfügen" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Rückgängig" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Wiederholen" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Schreibtisch in Dateien anzeigen" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Im Terminal öffnen" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Hintergrund ändern …" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Anzeigeeinstellungen" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Einstellungen" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Dateinamen eingeben …" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Start nicht erlauben" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Start erlauben" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Öffnen" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Mit anderer Anwendung öffnen" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Ausschneiden" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopieren" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Umbenennen …" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "In den Papierkorb verschieben" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Papierkorb leeren" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Eigenschaften" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "In Dateiverwaltung anzeigen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Symbolgröße" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Die Größe der Arbeitsflächensymbole festlegen." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Persönlichen Ordner anzeigen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Den persönlichen Ordner auf der Arbeitsfläche anzeigen." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Papierkorb-Symbol anzeigen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Das Papierkorb-Symbol auf der Arbeitsfläche anzeigen." ++ ++#~ msgid "Huge" ++#~ msgstr "Riesig" +diff --git a/extensions/desktop-icons/po/es.po b/extensions/desktop-icons/po/es.po +new file mode 100644 +index 00000000..8cc87da0 +--- /dev/null ++++ b/extensions/desktop-icons/po/es.po +@@ -0,0 +1,218 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR , YEAR. ++# Sergio Costas , 2018. ++# Daniel Mustieles , 2018-2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: 1.0\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-04 10:37+0100\n" ++"Last-Translator: Daniel Mustieles \n" ++"Language-Team: es \n" ++"Language: es\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Gtranslator 3.31.90\n" ++ ++#: createFolderDialog.js:48 ++#| msgid "New Folder" ++msgid "New folder name" ++msgstr "Nombre de la nueva carpeta" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Crear" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Cancelar" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Los nombres de carpetas no pueden contener «/»." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Una carpeta no se puede llamar «.»." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Una carpeta no se puede llamar «..»." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Las carpetas cuyo nombre empieza por «.» están ocultas." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Ya hay un archivo o carpeta con ese nombre." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Tamaño de los iconos del escritorio" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Pequeño" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Estándar" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostrar la carpeta personal en el escritorio" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostrar la papelera en el escritorio" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nueva carpeta" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Pegar" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Deshacer" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Rehacer" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Mostrar el escritorio en Archivos" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Abrir en una terminal" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Cambiar el fondo..." ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Configuración de pantalla" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Configuración" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Introduzca el nombre del archivo…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Aceptar" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "No permitir lanzar" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Permitir lanzar" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Abrir" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Abrir con otra aplicación" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Cortar" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Copiar" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Renombrar…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Mover a la papelera" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Vaciar la papelera" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Propiedades" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Mostrar en Files" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Tamaño de los iconos" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Establece el tamaño de los iconos del escritorio." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostrar la carpeta personal" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostrar la carpeta personal en el escritorio." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostrar la papelera" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostrar la papelera en el escritorio." ++ ++#~ msgid "Huge" ++#~ msgstr "Inmenso" ++ ++#~ msgid "Ok" ++#~ msgstr "Aceptar" ++ ++#~ msgid "huge" ++#~ msgstr "inmenso" ++ ++#~ msgid "Maximum width for the icons and filename." ++#~ msgstr "Ancho máximo de los iconos y el nombre de fichero." ++ ++#~ msgid "Shows the Documents folder in the desktop." ++#~ msgstr "Muestra la carpeta Documentos en el escritorio." ++ ++#~ msgid "Shows the Downloads folder in the desktop." ++#~ msgstr "Muestra la carpeta Descargas en el escritorio." ++ ++#~ msgid "Shows the Music folder in the desktop." ++#~ msgstr "Muestra la carpeta Música en el escritorio." ++ ++#~ msgid "Shows the Pictures folder in the desktop." ++#~ msgstr "Muestra la carpeta Imágenes en el escritorio." ++ ++#~ msgid "Shows the Videos folder in the desktop." ++#~ msgstr "Muestra la carpeta Vídeos en el escritorio." +diff --git a/extensions/desktop-icons/po/fi.po b/extensions/desktop-icons/po/fi.po +new file mode 100644 +index 00000000..71ac40df +--- /dev/null ++++ b/extensions/desktop-icons/po/fi.po +@@ -0,0 +1,191 @@ ++# Finnish translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Jiri Grönroos , 2018. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-02 11:29+0200\n" ++"Last-Translator: Jiri Grönroos \n" ++"Language-Team: Finnish \n" ++"Language: fi\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.0.6\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Uusi kansion nimi" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Luo" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Peru" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Kansion nimi ei voi sisältää merkkiä “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Kansion nimi ei voi olla “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Kansion nimi ei voi olla “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Kansiot, joiden nimi alkaa merkillä “.”, ovat piilotettuja." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Nimi on jo toisen tiedoston tai kansion käytössä." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Työpöytäkuvakkeiden koko" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Pieni" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Normaali" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Suuri" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Näytä kotikansio työpöydällä" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Näytä roskakorin kuvake työpöydällä" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Uusi kansio" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Liitä" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Kumoa" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Tee uudeleen" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Näytä työpöytä tiedostonhallinnassa" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Avaa päätteessä" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Vaihda taustakuvaa…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Näytön asetukset" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Asetukset" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Anna tiedostonimi…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Älä salli käynnistämistä" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Salli käynnistäminen" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Avaa" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Avaa toisella sovelluksella" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Leikkaa" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopioi" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Nimeä uudelleen…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Siirrä roskakoriin" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Tyhjennä roskakori" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Ominaisuudet" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Näytä tiedostonhallinnassa" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Kuvakekoko" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Aseta työpöytäkuvakkeiden koko." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Näytä kotikansio" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Näytä kotikansio työpöydällä." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Näytä roskakorin kuvake" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Näytä roskakorin kuvake työpöydällä." ++ ++#~ msgid "Huge" ++#~ msgstr "Valtava" +diff --git a/extensions/desktop-icons/po/fr.po b/extensions/desktop-icons/po/fr.po +new file mode 100644 +index 00000000..13e8f3a6 +--- /dev/null ++++ b/extensions/desktop-icons/po/fr.po +@@ -0,0 +1,164 @@ ++# French translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# ghentdebian , 2018. ++# Charles Monzat , 2018. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2018-12-14 09:12+0000\n" ++"PO-Revision-Date: 2018-12-16 17:47+0100\n" ++"Last-Translator: Charles Monzat \n" ++"Language-Team: GNOME French Team \n" ++"Language: fr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1)\n" ++"X-Generator: Gtranslator 3.30.0\n" ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Taille des icônes du bureau" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Petite" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Normale" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:102 ++msgid "Huge" ++msgstr "Immense" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Montrer le dossier personnel sur le bureau" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Montrer la corbeille sur le bureau" ++ ++#: desktopGrid.js:182 desktopGrid.js:301 ++msgid "New Folder" ++msgstr "Nouveau dossier" ++ ++#: desktopGrid.js:303 ++msgid "Paste" ++msgstr "Coller" ++ ++#: desktopGrid.js:304 ++msgid "Undo" ++msgstr "Annuler" ++ ++#: desktopGrid.js:305 ++msgid "Redo" ++msgstr "Refaire" ++ ++#: desktopGrid.js:307 ++msgid "Open Desktop in Files" ++msgstr "Ouvrir le bureau dans Fichiers" ++ ++#: desktopGrid.js:308 ++msgid "Open Terminal" ++msgstr "Ouvrir un terminal" ++ ++#: desktopGrid.js:310 ++msgid "Change Background…" ++msgstr "Changer l’arrière-plan…" ++ ++#: desktopGrid.js:311 ++msgid "Display Settings" ++msgstr "Configuration d’affichage" ++ ++#: desktopGrid.js:312 ++msgid "Settings" ++msgstr "Paramètres" ++ ++#: desktopGrid.js:568 ++msgid "Enter file name…" ++msgstr "Saisir un nom de fichier…" ++ ++#: desktopGrid.js:572 ++msgid "OK" ++msgstr "Valider" ++ ++#: desktopGrid.js:578 ++msgid "Cancel" ++msgstr "Annuler" ++ ++#: fileItem.js:485 ++msgid "Don’t Allow Launching" ++msgstr "Ne pas autoriser le lancement" ++ ++#: fileItem.js:487 ++msgid "Allow Launching" ++msgstr "Autoriser le lancement" ++ ++#: fileItem.js:550 ++msgid "Open" ++msgstr "Ouvrir" ++ ++#: fileItem.js:553 ++msgid "Cut" ++msgstr "Couper" ++ ++#: fileItem.js:554 ++msgid "Copy" ++msgstr "Copier" ++ ++#: fileItem.js:556 ++msgid "Rename" ++msgstr "Renommer" ++ ++#: fileItem.js:557 ++msgid "Move to Trash" ++msgstr "Mettre à la corbeille" ++ ++#: fileItem.js:567 ++msgid "Empty Trash" ++msgstr "Vider la corbeille" ++ ++#: fileItem.js:573 ++msgid "Properties" ++msgstr "Propriétés" ++ ++#: fileItem.js:575 ++msgid "Show in Files" ++msgstr "Montrer dans Fichiers" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Icon size" ++msgstr "Taille d’icônes" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:13 ++msgid "Set the size for the desktop icons." ++msgstr "Définir la taille des icônes du bureau." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show personal folder" ++msgstr "Montrer le dossier personnel" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:18 ++msgid "Show the personal folder in the desktop." ++msgstr "Montrer le dossier personnel sur le bureau." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show trash icon" ++msgstr "Montrer l’icône de la corbeille" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:23 ++msgid "Show the trash icon in the desktop." ++msgstr "Montrer la corbeille sur le bureau." ++ ++#~ msgid "Ok" ++#~ msgstr "Valider" +diff --git a/extensions/desktop-icons/po/fur.po b/extensions/desktop-icons/po/fur.po +new file mode 100644 +index 00000000..3ab6129f +--- /dev/null ++++ b/extensions/desktop-icons/po/fur.po +@@ -0,0 +1,187 @@ ++# Friulian translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Fabio Tomat , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-05 22:20+0100\n" ++"Last-Translator: Fabio Tomat \n" ++"Language-Team: Friulian \n" ++"Language: fur\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Gnûf non de cartele" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Cree" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Anule" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "I nons des cartelis no puedin contignî il caratar “/”" ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Une cartele no pues jessi clamade “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Une cartele no pues jessi clamade “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Lis cartelis cul “.” al inizi dal lôr non a son platadis." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Un file o une cartele cul stes non e esist za." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Dimension pes iconis dal scritori" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Piçule" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Largje" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostre la cartele personâl intal scritori" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostre la icone de scovacere intal scritori" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Gnove cartele" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Tache" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Anule" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Torne fâ" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Mostre Scritori in File" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Vierç in Terminâl" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Cambie sfont…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Impostazions visôr" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Impostazions" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Inserìs il non dal file…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Va ben" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "No sta permeti inviament" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Permet inviament" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Vierç" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Vierç cuntune altre aplicazion" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Taie" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Copie" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Cambie non..." ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Sposte te scovacere" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Disvuede scovacere" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Propietâts" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Mostre in File" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Dimension icone" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Stabilìs la dimension pes iconis dal scritori." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostre cartele personâl" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostre la cartele personâl intal scritori." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostre la icone de scovacere" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostre la icone de scovacere intal scritori." +diff --git a/extensions/desktop-icons/po/hr.po b/extensions/desktop-icons/po/hr.po +new file mode 100644 +index 00000000..0d26696c +--- /dev/null ++++ b/extensions/desktop-icons/po/hr.po +@@ -0,0 +1,186 @@ ++# Croatian translation for gnome-shell-extension-desktop-icons ++# Copyright (c) 2019 Rosetta Contributors and Canonical Ltd 2019 ++# This file is distributed under the same license as the gnome-shell-extension-desktop-icons package. ++# FIRST AUTHOR , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: gnome-shell-extension-desktop-icons\n" ++"Report-Msgid-Bugs-To: FULL NAME \n" ++"POT-Creation-Date: 2019-03-05 11:27+0000\n" ++"PO-Revision-Date: 2019-03-23 16:03+0000\n" ++"Last-Translator: gogo \n" ++"Language-Team: Croatian \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Launchpad-Export-Date: 2019-03-27 09:36+0000\n" ++"X-Generator: Launchpad (build 18910)\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Novi naziv mape" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Stvori" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Odustani" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Naziv mape ne može sadržavati “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Mapa se ne može nazvati “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Mapa se ne može nazvati “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mape sa “.” na početku njihovih naziva su skrivene." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Već postoji datoteka ili mapa s tim nazivom." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Veličina ikona radne površine" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Male" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standardne" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Velike" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Prikaži osobnu mapu na radnoj površini" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Prikaži mapu smeća na radnoj površini" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nova mapa" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Zalijepi" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Poništi" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Ponovi" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Prikaži radnu površinu u Datotekama" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Otvori u Terminalu" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Promijeni pozadinu…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Postavke zaslona" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Postavke" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Upiši naziv datoteke…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "U redu" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Ne dopuštaj pokretanje" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Dopusti pokretanje" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Otvori" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Otvori s drugom aplikacijom" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Izreži" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopiraj" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Preimenuj…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Premjesti u smeće" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Isprazni smeće" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Svojstva" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Prikaži u Datotekama" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Veličina ikona" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Postavi veličinu ikona radne površine." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Prikaži osobnu mapu" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Prikaži osobnu mapu na radnoj površini." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Prikaži ikonu smeća" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Prikaži ikonu smeća na radnoj površini." +diff --git a/extensions/desktop-icons/po/hu.po b/extensions/desktop-icons/po/hu.po +new file mode 100644 +index 00000000..a350dd1a +--- /dev/null ++++ b/extensions/desktop-icons/po/hu.po +@@ -0,0 +1,190 @@ ++# Hungarian translation for desktop-icons. ++# Copyright (C) 2019 The Free Software Foundation, inc. ++# This file is distributed under the same license as the desktop-icons package. ++# ++# Balázs Úr , 2019. ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-i" ++"cons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-07 23:45+0100\n" ++"Last-Translator: Balázs Úr \n" ++"Language-Team: Hungarian \n" ++"Language: hu\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Lokalize 2.0\n" ++ ++#: createFolderDialog.js:48 ++#| msgid "New Folder" ++msgid "New folder name" ++msgstr "Új mappa neve" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Létrehozás" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Mégse" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "A mappanevek nem tartalmazhatnak „/” karaktert." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Egy mappának nem lehet „.” a neve." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Egy mappának nem lehet „..” a neve." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "A „.” karakterrel kezdődő nevű mappák rejtettek." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Már van egy fájl vagy mappa azzal a névvel." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Az asztali ikonok mérete" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Kicsi" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Szabványos" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Nagy" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "A személyes mappa megjelenítése az asztalon" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "A kuka ikon megjelenítése az asztalon" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Új mappa" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Beillesztés" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Visszavonás" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Újra" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Asztal megjelenítése a Fájlokban" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Megnyitás terminálban" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Háttér megváltoztatása…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Megjelenítés beállításai" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Beállítások" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Adjon meg egy fájlnevet…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Rendben" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Ne engedélyezzen indítást" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Indítás engedélyezése" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Megnyitás" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Megnyitás egyéb alkalmazással" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Kivágás" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Másolás" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Átnevezés…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Áthelyezés a Kukába" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Kuka ürítése" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Tulajdonságok" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Megjelenítés a Fájlokban" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ikonméret" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Az asztali ikonok méretének beállítása." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Személyes mappa megjelenítése" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "A személyes mappa megjelenítése az asztalon." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Kuka ikon megjelenítése" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "A kuka ikon megjelenítése az asztalon." ++ +diff --git a/extensions/desktop-icons/po/id.po b/extensions/desktop-icons/po/id.po +new file mode 100644 +index 00000000..b809c3d1 +--- /dev/null ++++ b/extensions/desktop-icons/po/id.po +@@ -0,0 +1,190 @@ ++# Indonesian translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Kukuh Syafaat , 2018, 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-02 19:13+0700\n" ++"Last-Translator: Kukuh Syafaat \n" ++"Language-Team: Indonesian \n" ++"Language: id\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nama folder baru" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Buat" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Batal" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Nama folder tak boleh memuat \"/\"." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Sebuah folder tak bisa dinamai \".\"." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Sebuah folder tak bisa dinamai \"..\"." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Folder dengan \".\" di awal nama mereka disembunyikan." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Folder dengan nama itu sudah ada." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Ukuran untuk ikon destop" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Kecil" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standar" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Besar" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Tampilkan folder pribadi di destop" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Tampilkan ikon tong sampah di destop" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Folder Baru" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Tempel" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Tak Jadi" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Jadi Lagi" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Tampilkan Destop pada Berkas" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Buka dalam Terminal" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Ubah Latar Belakang…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Pengaturan Tampilan" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Pengaturan" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Masukkan nama berkas…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Jangan Izinkan Peluncuran" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Izinkan Peluncuran" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Buka" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Buka Dengan Aplikasi Lain" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Potong" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Salin" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Ganti Nama…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Pindahkan ke Tong Sampah" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Kosongkan Tong Sampah" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Properti" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Tampilkan pada Berkas" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ukuran ikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Set ukuran untuk ikon destop." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Tampilkan folder pribadi" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Tampilkan folder pribadi di destop." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Tampilkan ikon tong sampah" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Tampilkan ikon tong sampah di destop." ++ ++#~ msgid "Huge" ++#~ msgstr "Sangat besar" +diff --git a/extensions/desktop-icons/po/it.po b/extensions/desktop-icons/po/it.po +new file mode 100644 +index 00000000..5001da46 +--- /dev/null ++++ b/extensions/desktop-icons/po/it.po +@@ -0,0 +1,189 @@ ++# Italian translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Massimo Branchini , 2019. ++# Milo Casagrande , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-12 09:51+0100\n" ++"Last-Translator: Milo Casagrande \n" ++"Language-Team: Italian \n" ++"Language: it\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nuova cartella" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Crea" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Annulla" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "I nomi di cartelle non possono contenere il carattere «/»" ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Una cartella non può essere chiamata «.»." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Una cartella non può essere chiamata «..»." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Cartelle il cui nome inizia con «.» sono nascoste." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Esiste già un file o una cartella con quel nome." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Dimensione delle icone della scrivania" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Piccola" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Normale" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostra la cartella personale sulla scrivania" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostra il cestino sulla scrivania" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nuova cartella" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Incolla" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Annulla" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Ripeti" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Mostra la scrivania in File" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Apri in Terminale" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Cambia lo sfondo…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Impostazioni dello schermo" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Impostazioni" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Indicare un nome per il file…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Ok" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Non permettere l'esecuzione" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Permetti l'esecuzione" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Apri" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Apri con altra applicazione" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Taglia" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Copia" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Rinomina…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Sposta nel cestino" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Svuota il cestino" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Proprietà" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Mostra in File" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Dimensione dell'icona" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Imposta la grandezza delle icone della scrivania." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostra la cartella personale" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostra la cartella personale sulla scrivania." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostra il cestino" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostra il cestino sulla scrivania." +diff --git a/extensions/desktop-icons/po/ja.po b/extensions/desktop-icons/po/ja.po +new file mode 100644 +index 00000000..3b103e02 +--- /dev/null ++++ b/extensions/desktop-icons/po/ja.po +@@ -0,0 +1,187 @@ ++# Japanese translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# sicklylife , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-14 12:56+0000\n" ++"PO-Revision-Date: 2019-03-15 06:30+0000\n" ++"Last-Translator: sicklylife \n" ++"Language-Team: Japanese \n" ++"Language: ja\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "新しいフォルダー名" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "作成" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "キャンセル" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "“/”は、フォルダー名に含められません。" ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "“.”という名前をフォルダーに付けられません。" ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "“..”という名前をフォルダーに付けられません。" ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "名前が“.”で始まるフォルダーは、隠しフォルダーになります。" ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "その名前のファイルかフォルダーがすでに存在します。" ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "デスクトップアイコンのサイズ" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "小さい" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "標準" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "大きい" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "デスクトップにホームフォルダーを表示する" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "デスクトップにゴミ箱を表示する" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "新しいフォルダー" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "貼り付け" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "元に戻す" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "やり直す" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "“ファイル”でデスクトップを表示する" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "端末を開く" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "背景を変更する…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "ディスプレイの設定" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "設定" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "ファイル名を入力してください…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "起動を許可しない" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "起動を許可する" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "開く" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "別のアプリケーションで開く" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "切り取り" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "コピー" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "名前の変更…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "ゴミ箱へ移動する" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "ゴミ箱を空にする" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "プロパティ" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "“ファイル”で表示する" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "アイコンサイズ" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "デスクトップのアイコンサイズを設定します。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "ホームフォルダーを表示する" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "デスクトップにホームフォルダーを表示します。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "ゴミ箱アイコンを表示する" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "デスクトップにゴミ箱のアイコンを表示します。" +diff --git a/extensions/desktop-icons/po/meson.build b/extensions/desktop-icons/po/meson.build +new file mode 100644 +index 00000000..b2e9e422 +--- /dev/null ++++ b/extensions/desktop-icons/po/meson.build +@@ -0,0 +1 @@ ++i18n.gettext (meson.project_name (), preset: 'glib') +diff --git a/extensions/desktop-icons/po/nl.po b/extensions/desktop-icons/po/nl.po +new file mode 100644 +index 00000000..b2f7dab6 +--- /dev/null ++++ b/extensions/desktop-icons/po/nl.po +@@ -0,0 +1,188 @@ ++# Dutch translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Nathan Follens , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-04 19:46+0100\n" ++"Last-Translator: Nathan Follens \n" ++"Language-Team: Dutch \n" ++"Language: nl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nieuwe mapnaam" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Aanmaken" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Annuleren" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Mapnamen kunnen geen ‘/’ bevatten." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Een map kan niet ‘.’ worden genoemd." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Een map kan niet ‘..’ worden genoemd." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mappen waarvan de naam begint met ‘.’ zijn verborgen." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Er bestaat al een bestand of map met die naam." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Grootte van bureaubladpictogrammen" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Klein" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standaard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Groot" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Toon de persoonlijke map op het bureaublad" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Toon het prullenbakpictogram op het bureaublad" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nieuwe map" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Plakken" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Ongedaan maken" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Opnieuw" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Bureaublad tonen in Bestanden" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Openen in terminalvenster" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Achtergrond aanpassen…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Scherminstellingen" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Instellingen" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Voer bestandsnaam in…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Oké" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Toepassingen starten niet toestaan" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Toepassingen starten toestaan" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Openen" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Met andere toepassing openen" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Knippen" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopiëren" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Hernoemen…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Verplaatsen naar prullenbak" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Prullenbak legen" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Eigenschappen" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Tonen in Bestanden" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Pictogramgrootte" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Stel de grootte van de bureaubladpictogrammen in." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Persoonlijke map tonen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Toon de persoonlijke map op het bureaublad." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Prullenbakpictogram tonen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Toon het prullenbakpictogram op het bureaublad." +diff --git a/extensions/desktop-icons/po/pl.po b/extensions/desktop-icons/po/pl.po +new file mode 100644 +index 00000000..f57b3be8 +--- /dev/null ++++ b/extensions/desktop-icons/po/pl.po +@@ -0,0 +1,193 @@ ++# Polish translation for desktop-icons. ++# Copyright © 2018-2019 the desktop-icons authors. ++# This file is distributed under the same license as the desktop-icons package. ++# Piotr Drąg , 2018-2019. ++# Aviary.pl , 2018-2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-05-01 13:03+0200\n" ++"Last-Translator: Piotr Drąg \n" ++"Language-Team: Polish \n" ++"Language: pl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " ++"|| n%100>=20) ? 1 : 2);\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nazwa nowego katalogu" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Utwórz" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Anuluj" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Nazwy katalogów nie mogą zawierać znaku „/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Katalog nie może mieć nazwy „.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Katalog nie może mieć nazwy „..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Katalogi z „.” na początku nazwy są ukryte." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Plik lub katalog o tej nazwie już istnieje." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Rozmiar ikon na pulpicie" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Mały" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standardowy" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Duży" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Katalog domowy na pulpicie" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Kosz na pulpicie" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Nowy katalog" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Wklej" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Cofnij" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Ponów" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Wyświetl pulpit w menedżerze plików" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Otwórz w terminalu" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Zmień tło…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Ustawienia ekranu" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Ustawienia" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Nazwa pliku…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Nie odnaleziono polecenia" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Nie zezwalaj na uruchamianie" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Zezwól na uruchamianie" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Otwórz" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Otwórz za pomocą innego programu" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Wytnij" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Skopiuj" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Zmień nazwę…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Przenieś do kosza" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Opróżnij kosz" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Właściwości" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Wyświetl w menedżerze plików" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Rozmiar ikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Ustawia rozmiar ikon na pulpicie." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Katalog domowy" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Wyświetla katalog domowy na pulpicie." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Kosz" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Wyświetla kosz na pulpicie." +diff --git a/extensions/desktop-icons/po/pt_BR.po b/extensions/desktop-icons/po/pt_BR.po +new file mode 100644 +index 00000000..8d61c72e +--- /dev/null ++++ b/extensions/desktop-icons/po/pt_BR.po +@@ -0,0 +1,199 @@ ++# Brazilian Portuguese translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Enrico Nicoletto , 2018. ++# Rafael Fontenelle , 2018-2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-04-29 17:35-0300\n" ++"Last-Translator: Rafael Fontenelle \n" ++"Language-Team: Brazilian Portuguese \n" ++"Language: pt_BR\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1)\n" ++"X-Generator: Gtranslator 3.32.0\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nome da nova pasta" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Criar" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Cancelar" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Nomes de pastas não podem conter “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Uma pasta não pode ser chamada “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Uma pasta não pode ser chamada “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Pastas com “.” no começo de seus nomes são ocultas." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Já existe um arquivo ou uma pasta com esse nome." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Tamanho para os ícones da área de trabalho" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Pequeno" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Padrão" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostrar a pasta pessoal na área de trabalho" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostrar o ícone da lixeira na área de trabalho" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Nova pasta" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Colar" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Desfazer" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Refazer" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Mostrar a área de trabalho no Arquivos" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Abrir no terminal" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Alterar plano de fundo…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Configurações de exibição" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Configurações" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Insira um nome de arquivo…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Comando não encontrado" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Não permitir iniciar" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Permitir iniciar" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Abrir" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Abrir com outro aplicativo" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Recortar" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Copiar" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Renomear…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Mover para a lixeira" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Esvaziar lixeira" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Propriedades" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Mostrar no Arquivos" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Tamanho do ícone" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Define o tamanho para os ícones da área de trabalho." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostrar pasta pessoal" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostra a pasta pessoal na área de trabalho." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostrar ícone da lixeira" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostra o ícone da lixeira na área de trabalho." ++ ++#~ msgid "Huge" ++#~ msgstr "Enorme" ++ ++#~ msgid "Ok" ++#~ msgstr "Ok" +diff --git a/extensions/desktop-icons/po/ru.po b/extensions/desktop-icons/po/ru.po +new file mode 100644 +index 00000000..4094f166 +--- /dev/null ++++ b/extensions/desktop-icons/po/ru.po +@@ -0,0 +1,153 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# Eaglers , 2018. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: \n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2018-11-22 08:42+0000\n" ++"PO-Revision-Date: 2018-11-22 22:02+0300\n" ++"Last-Translator: Stas Solovey \n" ++"Language-Team: Russian \n" ++"Language: ru\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" ++"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++"X-Generator: Poedit 2.2\n" ++ ++#: prefs.js:89 ++msgid "Size for the desktop icons" ++msgstr "Размер значков" ++ ++#: prefs.js:89 ++msgid "Small" ++msgstr "Маленький" ++ ++#: prefs.js:89 ++msgid "Standard" ++msgstr "Стандартный" ++ ++#: prefs.js:89 ++msgid "Large" ++msgstr "Большой" ++ ++#: prefs.js:89 ++msgid "Huge" ++msgstr "Огромный" ++ ++#: prefs.js:90 ++msgid "Show the personal folder in the desktop" ++msgstr "Показывать домашнюю папку на рабочем столе" ++ ++#: prefs.js:91 ++msgid "Show the trash icon in the desktop" ++msgstr "Показывать «Корзину» на рабочем столе" ++ ++#: desktopGrid.js:185 desktopGrid.js:304 ++msgid "New Folder" ++msgstr "Создать папку" ++ ++#: desktopGrid.js:306 ++msgid "Paste" ++msgstr "Вставить" ++ ++#: desktopGrid.js:307 ++msgid "Undo" ++msgstr "Отменить" ++ ++#: desktopGrid.js:308 ++msgid "Redo" ++msgstr "Повторить" ++ ++#: desktopGrid.js:310 ++msgid "Open Desktop in Files" ++msgstr "Открыть «Рабочий стол» в «Файлах»" ++ ++#: desktopGrid.js:311 ++msgid "Open Terminal" ++msgstr "Открыть терминал" ++ ++#: desktopGrid.js:313 ++msgid "Change Background…" ++msgstr "Изменить фон…" ++ ++#: desktopGrid.js:314 ++msgid "Display Settings" ++msgstr "Настройки дисплея" ++ ++#: desktopGrid.js:315 ++msgid "Settings" ++msgstr "Параметры" ++ ++#: desktopGrid.js:569 ++msgid "Enter file name…" ++msgstr "Ввести имя файла…" ++ ++#: desktopGrid.js:573 ++msgid "Ok" ++msgstr "ОК" ++ ++#: desktopGrid.js:579 ++msgid "Cancel" ++msgstr "Отмена" ++ ++#: fileItem.js:390 ++msgid "Open" ++msgstr "Открыть" ++ ++#: fileItem.js:393 ++msgid "Cut" ++msgstr "Вырезать" ++ ++#: fileItem.js:394 ++msgid "Copy" ++msgstr "Вставить" ++ ++#: fileItem.js:395 ++msgid "Rename" ++msgstr "Переименовать" ++ ++#: fileItem.js:396 ++msgid "Move to Trash" ++msgstr "Переместить в корзину" ++ ++#: fileItem.js:400 ++msgid "Empty trash" ++msgstr "Очистить корзину" ++ ++#: fileItem.js:406 ++msgid "Properties" ++msgstr "Свойства" ++ ++#: fileItem.js:408 ++msgid "Show in Files" ++msgstr "Показать в «Файлах»" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Icon size" ++msgstr "Размер значков" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:13 ++msgid "Set the size for the desktop icons." ++msgstr "Установить размер значков на рабочем столе." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show personal folder" ++msgstr "Показывать домашнюю папку" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:18 ++msgid "Show the personal folder in the desktop." ++msgstr "Показывать значок домашней папки на рабочем столе." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show trash icon" ++msgstr "Показывать значок корзины" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:23 ++msgid "Show the trash icon in the desktop." ++msgstr "Показывать значок корзины на рабочем столе." +diff --git a/extensions/desktop-icons/po/sv.po b/extensions/desktop-icons/po/sv.po +new file mode 100644 +index 00000000..928cbe90 +--- /dev/null ++++ b/extensions/desktop-icons/po/sv.po +@@ -0,0 +1,197 @@ ++# Swedish translation for desktop-icons. ++# Copyright © 2018, 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Anders Jonsson , 2018, 2019. ++# Josef Andersson , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-11 21:50+0100\n" ++"Last-Translator: Anders Jonsson \n" ++"Language-Team: Swedish \n" ++"Language: sv\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nytt mappnamn" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Skapa" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Avbryt" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Mappnamn kan inte innehålla ”/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "En mapp kan inte kallas ”.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "En mapp kan inte kallas ”..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mappar med ”.” i början på sitt namn är dolda." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Det finns redan en fil eller mapp med det namnet" ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Storlek för skrivbordsikonerna" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Liten" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Stor" ++ ++# TODO: *ON* the desktop? ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Visa den personliga mappen på skrivbordet" ++ ++# TODO: *ON* the desktop? ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Visa papperskorgsikonen på skrivbordet" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Ny mapp" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Klistra in" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Ångra" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Gör om" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Visa skrivbord i Filer" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Öppna i terminal" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Ändra bakgrund…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Visningsinställningar" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Inställningar" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Ange filnamn…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Tillåt ej programstart" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Tillåt programstart" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Öppna" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Öppna med annat program" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Klipp ut" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopiera" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Byt namn…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Flytta till papperskorgen" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Töm papperskorgen" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Egenskaper" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Visa i Filer" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ikonstorlek" ++ ++# TODO: *ON* the desktop? ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Ställ in storleken för skrivbordsikonerna." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Visa personlig mapp" ++ ++# TODO: *ON* the desktop? ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Visa den personliga mappen på skrivbordet." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Visa papperskorgsikon" ++ ++# TODO: *ON* the desktop? ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Visa papperskorgsikonen på skrivbordet." ++ ++#~ msgid "Huge" ++#~ msgstr "Enorm" +diff --git a/extensions/desktop-icons/po/tr.po b/extensions/desktop-icons/po/tr.po +new file mode 100644 +index 00000000..2e5f5a7f +--- /dev/null ++++ b/extensions/desktop-icons/po/tr.po +@@ -0,0 +1,191 @@ ++# Turkish translation for desktop-icons. ++# Copyright (C) 2000-2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# ++# Sabri Ünal , 2019. ++# Serdar Sağlam , 2019 ++# Emin Tufan Çetin , 2019. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: \n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-09 14:47+0000\n" ++"PO-Revision-Date: 2019-03-13 13:43+0300\n" ++"Last-Translator: Emin Tufan Çetin \n" ++"Language-Team: Türkçe \n" ++"Language: tr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Gtranslator 3.30.1\n" ++"Plural-Forms: nplurals=1; plural=0;\n" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Yeni klasör adı" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Oluştur" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "İptal" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Klasör adları “/” içeremez." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Bir klasör “.” olarak adlandırılamaz." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Bir klasör “..” olarak adlandırılamaz." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Adlarının başında “.” bulunan klasörler gizlenir." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Zaten bu adda bir dosya veya klasör var." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Masaüstü simgeleri boyutu" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Küçük" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standart" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Büyük" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Kişisel klasörü masaüstünde göster" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Çöp kutusunu masaüstünde göster" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Yeni Klasör" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Yapıştır" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Geri Al" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Yinele" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Masaüstünü Dosyalarʼda Göster" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Uçbirimde Aç" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Arka Planı Değiştir…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Görüntü Ayarları" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Ayarlar" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Dosya adını gir…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Tamam" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Başlatmaya İzin Verme" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Başlatmaya İzin Ver" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Aç" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Başka Uygulamayla Aç" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Kes" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopyala" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Yeniden Adlandır…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Çöpe Taşı" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Çöpü Boşalt" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Özellikler" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Dosyalarʼda Göster" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Simge boyutu" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Masaüstü simgelerinin boyutunu ayarla." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Kişisel klasörü göster" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Kişisel klasörü masaüstünde göster." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Çöp kutusunu göster" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Çöp kutusu simgesini masaüstünde göster." +diff --git a/extensions/desktop-icons/po/zh_TW.po b/extensions/desktop-icons/po/zh_TW.po +new file mode 100644 +index 00000000..8ce4ab98 +--- /dev/null ++++ b/extensions/desktop-icons/po/zh_TW.po +@@ -0,0 +1,135 @@ ++# Chinese (Taiwan) translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Yi-Jyun Pan , 2018. ++# ++msgid "" ++msgstr "" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2018-10-22 14:12+0000\n" ++"PO-Revision-Date: 2018-10-24 21:31+0800\n" ++"Language-Team: Chinese (Taiwan) \n" ++"Language: zh_TW\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Last-Translator: pan93412 \n" ++"X-Generator: Poedit 2.2\n" ++ ++#: prefs.js:89 ++msgid "Size for the desktop icons" ++msgstr "桌面圖示的大小" ++ ++#: prefs.js:89 ++msgid "Small" ++msgstr "小圖示" ++ ++#: prefs.js:89 ++msgid "Standard" ++msgstr "標準大小圖示" ++ ++#: prefs.js:89 ++msgid "Large" ++msgstr "大圖示" ++ ++#: prefs.js:89 ++msgid "Huge" ++msgstr "巨大圖示" ++ ++#: prefs.js:90 ++msgid "Show the personal folder in the desktop" ++msgstr "在桌面顯示個人資料夾" ++ ++#: prefs.js:91 ++msgid "Show the trash icon in the desktop" ++msgstr "在桌面顯示垃圾桶圖示" ++ ++#: desktopGrid.js:178 desktopGrid.js:297 ++msgid "New Folder" ++msgstr "新增資料夾" ++ ++#: desktopGrid.js:299 ++msgid "Paste" ++msgstr "貼上" ++ ++#: desktopGrid.js:300 ++msgid "Undo" ++msgstr "復原" ++ ++#: desktopGrid.js:301 ++msgid "Redo" ++msgstr "重做" ++ ++#: desktopGrid.js:303 ++msgid "Open Desktop in Files" ++msgstr "在《檔案》中開啟桌面" ++ ++#: desktopGrid.js:304 ++msgid "Open Terminal" ++msgstr "開啟終端器" ++ ++#: desktopGrid.js:306 ++msgid "Change Background…" ++msgstr "變更背景圖片…" ++ ++#: desktopGrid.js:307 ++msgid "Display Settings" ++msgstr "顯示設定" ++ ++#: desktopGrid.js:308 ++msgid "Settings" ++msgstr "設定" ++ ++#: fileItem.js:223 ++msgid "Open" ++msgstr "開啟" ++ ++#: fileItem.js:226 ++msgid "Cut" ++msgstr "剪下" ++ ++#: fileItem.js:227 ++msgid "Copy" ++msgstr "複製" ++ ++#: fileItem.js:228 ++msgid "Move to Trash" ++msgstr "移動到垃圾桶" ++ ++#: fileItem.js:232 ++msgid "Empty trash" ++msgstr "清空回收桶" ++ ++#: fileItem.js:238 ++msgid "Properties" ++msgstr "屬性" ++ ++#: fileItem.js:240 ++msgid "Show in Files" ++msgstr "在《檔案》中顯示" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Icon size" ++msgstr "圖示大小" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:13 ++msgid "Set the size for the desktop icons." ++msgstr "設定桌面圖示的大小。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show personal folder" ++msgstr "顯示個人資料夾" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:18 ++msgid "Show the personal folder in the desktop." ++msgstr "在桌面顯示個人資料夾。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show trash icon" ++msgstr "顯示垃圾桶圖示" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:23 ++msgid "Show the trash icon in the desktop." ++msgstr "在桌面顯示垃圾桶圖示。" +diff --git a/extensions/desktop-icons/prefs.js b/extensions/desktop-icons/prefs.js +new file mode 100644 +index 00000000..4b8d986e +--- /dev/null ++++ b/extensions/desktop-icons/prefs.js +@@ -0,0 +1,159 @@ ++ ++/* Desktop Icons GNOME Shell extension ++ * ++ * Copyright (C) 2017 Carlos Soriano ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Gtk = imports.gi.Gtk; ++const GObject = imports.gi.GObject; ++const Gio = imports.gi.Gio; ++const GioSSS = Gio.SettingsSchemaSource; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Gettext = imports.gettext; ++ ++const Config = imports.misc.config; ++ ++var _ = Gettext.domain('desktop-icons').gettext; ++ ++const SCHEMA_NAUTILUS = 'org.gnome.nautilus.preferences'; ++const SCHEMA_GTK = 'org.gtk.Settings.FileChooser'; ++const SCHEMA = 'org.gnome.shell.extensions.desktop-icons'; ++ ++const ICON_SIZE = { 'small': 48, 'standard': 64, 'large': 96 }; ++const ICON_WIDTH = { 'small': 120, 'standard': 128, 'large': 128 }; ++const ICON_HEIGHT = { 'small': 98, 'standard': 114, 'large': 146 }; ++ ++var FileType = { ++ NONE: null, ++ USER_DIRECTORY_HOME: 'show-home', ++ USER_DIRECTORY_TRASH: 'show-trash', ++} ++ ++var nautilusSettings; ++var gtkSettings; ++var settings; ++// This is already in Nautilus settings, so it should not be made tweakable here ++var CLICK_POLICY_SINGLE = false; ++ ++function initTranslations() { ++ let extension = ExtensionUtils.getCurrentExtension(); ++ ++ let localedir = extension.dir.get_child('locale'); ++ if (localedir.query_exists(null)) ++ Gettext.bindtextdomain('desktop-icons', localedir.get_path()); ++ else ++ Gettext.bindtextdomain('desktop-icons', Config.LOCALEDIR); ++} ++ ++function init() { ++ let schemaSource = GioSSS.get_default(); ++ let schemaGtk = schemaSource.lookup(SCHEMA_GTK, true); ++ gtkSettings = new Gio.Settings({ settings_schema: schemaGtk }); ++ let schemaObj = schemaSource.lookup(SCHEMA_NAUTILUS, true); ++ if (!schemaObj) { ++ nautilusSettings = null; ++ } else { ++ nautilusSettings = new Gio.Settings({ settings_schema: schemaObj });; ++ nautilusSettings.connect('changed', _onNautilusSettingsChanged); ++ _onNautilusSettingsChanged(); ++ } ++ settings = get_schema(SCHEMA); ++} ++ ++function get_schema(schema) { ++ let extension = ExtensionUtils.getCurrentExtension(); ++ ++ // check if this extension was built with "make zip-file", and thus ++ // has the schema files in a subfolder ++ // otherwise assume that extension has been installed in the ++ // same prefix as gnome-shell (and therefore schemas are available ++ // in the standard folders) ++ let schemaDir = extension.dir.get_child('schemas'); ++ let schemaSource; ++ if (schemaDir.query_exists(null)) ++ schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), GioSSS.get_default(), false); ++ else ++ schemaSource = GioSSS.get_default(); ++ ++ let schemaObj = schemaSource.lookup(schema, true); ++ if (!schemaObj) ++ throw new Error('Schema ' + schema + ' could not be found for extension ' + extension.metadata.uuid + '. Please check your installation.'); ++ ++ return new Gio.Settings({ settings_schema: schemaObj }); ++} ++ ++function buildPrefsWidget() { ++ initTranslations(); ++ let frame = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, border_width: 10, spacing: 10 }); ++ ++ frame.add(buildSelector('icon-size', _("Size for the desktop icons"), { 'small': _("Small"), 'standard': _("Standard"), 'large': _("Large") })); ++ frame.add(buildSwitcher('show-home', _("Show the personal folder in the desktop"))); ++ frame.add(buildSwitcher('show-trash', _("Show the trash icon in the desktop"))); ++ frame.show_all(); ++ return frame; ++} ++ ++function buildSwitcher(key, labelText) { ++ let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 10 }); ++ let label = new Gtk.Label({ label: labelText, xalign: 0 }); ++ let switcher = new Gtk.Switch({ active: settings.get_boolean(key) }); ++ settings.bind(key, switcher, 'active', 3); ++ hbox.pack_start(label, true, true, 0); ++ hbox.add(switcher); ++ return hbox; ++} ++ ++function buildSelector(key, labelText, elements) { ++ let listStore = new Gtk.ListStore(); ++ listStore.set_column_types ([GObject.TYPE_STRING, GObject.TYPE_STRING]); ++ let schemaKey = settings.settings_schema.get_key(key); ++ let values = schemaKey.get_range().get_child_value(1).get_child_value(0).get_strv(); ++ for (let val of values) { ++ let iter = listStore.append(); ++ let visibleText = val; ++ if (visibleText in elements) ++ visibleText = elements[visibleText]; ++ listStore.set (iter, [0, 1], [visibleText, val]); ++ } ++ let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 10 }); ++ let label = new Gtk.Label({ label: labelText, xalign: 0 }); ++ let combo = new Gtk.ComboBox({model: listStore}); ++ let rendererText = new Gtk.CellRendererText(); ++ combo.pack_start (rendererText, false); ++ combo.add_attribute (rendererText, 'text', 0); ++ combo.set_id_column(1); ++ settings.bind(key, combo, 'active-id', 3); ++ hbox.pack_start(label, true, true, 0); ++ hbox.add(combo); ++ return hbox; ++} ++ ++function _onNautilusSettingsChanged() { ++ CLICK_POLICY_SINGLE = nautilusSettings.get_string('click-policy') == 'single'; ++} ++ ++function get_icon_size() { ++ // this one doesn't need scaling because Gnome Shell automagically scales the icons ++ return ICON_SIZE[settings.get_string('icon-size')]; ++} ++ ++function get_desired_width(scale_factor) { ++ return ICON_WIDTH[settings.get_string('icon-size')] * scale_factor; ++} ++ ++function get_desired_height(scale_factor) { ++ return ICON_HEIGHT[settings.get_string('icon-size')] * scale_factor; ++} +diff --git a/extensions/desktop-icons/schemas/meson.build b/extensions/desktop-icons/schemas/meson.build +new file mode 100644 +index 00000000..2b179165 +--- /dev/null ++++ b/extensions/desktop-icons/schemas/meson.build +@@ -0,0 +1,6 @@ ++gnome.compile_schemas() ++ ++install_data( ++ 'org.gnome.shell.extensions.desktop-icons.gschema.xml', ++ install_dir : schema_dir ++) +diff --git a/extensions/desktop-icons/schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml b/extensions/desktop-icons/schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml +new file mode 100644 +index 00000000..bb4e50f3 +--- /dev/null ++++ b/extensions/desktop-icons/schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml +@@ -0,0 +1,25 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 'standard' ++ Icon size ++ Set the size for the desktop icons. ++ ++ ++ true ++ Show personal folder ++ Show the personal folder in the desktop. ++ ++ ++ true ++ Show trash icon ++ Show the trash icon in the desktop. ++ ++ ++ +diff --git a/extensions/desktop-icons/stylesheet.css b/extensions/desktop-icons/stylesheet.css +new file mode 100644 +index 00000000..17d4b328 +--- /dev/null ++++ b/extensions/desktop-icons/stylesheet.css +@@ -0,0 +1,38 @@ ++.file-item { ++ padding: 4px; ++ border: 1px; ++ margin: 1px; ++} ++ ++.file-item:hover { ++ background-color: rgba(238, 238, 238, 0.2); ++} ++ ++.name-label { ++ text-shadow: 1px 1px black; ++ color: white; ++ text-align: center; ++} ++ ++.draggable { ++ background-color: red; ++} ++ ++.rename-popup { ++ min-width: 300px; ++ margin: 6px; ++} ++ ++.create-folder-dialog-entry { ++ width: 20em; ++ margin-bottom: 6px; ++} ++ ++.create-folder-dialog-label { ++ padding-bottom: .4em; ++} ++ ++.create-folder-dialog-error-box { ++ padding-top: 16px; ++ spacing: 6px; ++} +diff --git a/meson.build b/meson.build +index cf855a01..6e8c41f6 100644 +--- a/meson.build ++++ b/meson.build +@@ -33,6 +33,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com' + + classic_extensions = [ + 'apps-menu', ++ 'desktop-icons', + 'places-menu', + 'launch-new-instance', + 'window-list' +diff --git a/po/ca.po b/po/ca.po +index f3be74c0..53a097f0 100644 +--- a/po/ca.po ++++ b/po/ca.po +@@ -1,11 +1,19 @@ ++# #-#-#-#-# ca.po (gnome-shell-extensions) #-#-#-#-# + # Catalan translation for gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # Jordi Mas i Hernandez , 2011. + # Gil Forcada , 2012, 2013, 2014. + # ++# #-#-#-#-# ca.po (1.0) #-#-#-#-# ++# ++# This file is distributed under the same license as the PACKAGE package. ++# Jordi Mas i Hernandez , 2019 ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ca.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -18,6 +26,20 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=n != 1;\n" ++"#-#-#-#-# ca.po (1.0) #-#-#-#-#\n" ++"Project-Id-Version: 1.0\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-07-22 10:24+0200\n" ++"PO-Revision-Date: 2019-07-22 10:24+0200\n" ++"Language: ca\n" ++"Language-Team: Catalan \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Last-Translator: Jordi Mas \n" ++"Language: ca\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -362,6 +384,178 @@ msgstr "Nom" + msgid "Workspace %d" + msgstr "Espai de treball %d" + ++#: ../createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nom de la carpeta nou" ++ ++#: ../createFolderDialog.js:72 ++msgid "Create" ++msgstr "Crea" ++ ++#: ../createFolderDialog.js:74 ../desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Cancel·la" ++ ++#: ../createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Els noms de carpetes no poden contenir «/»." ++ ++#: ../createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Una carpeta no es pot anomenar «.»." ++ ++#: ../createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Una carpeta no es pot anomenar «..»." ++ ++#: ../createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Les carpetes amb un «.» a l'inici del seu nom s'amaguen." ++ ++#: ../createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Ja existeix un fitxer o carpeta amb aquest nom." ++ ++#: ../prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Mida de les icones d'escriptori" ++ ++#: ../prefs.js:102 ++msgid "Small" ++msgstr "Petita" ++ ++#: ../prefs.js:102 ++msgid "Standard" ++msgstr "Estàndard" ++ ++#: ../prefs.js:102 ++msgid "Large" ++msgstr "Gran" ++ ++#: ../prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostra la carpeta personal a l'escriptori" ++ ++#: ../prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostra la icona de la paperera a l'escriptori" ++ ++#: ../desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Carpeta nova" ++ ++#: ../desktopGrid.js:325 ++msgid "Paste" ++msgstr "Enganxa" ++ ++#: ../desktopGrid.js:326 ++msgid "Undo" ++msgstr "Desfés" ++ ++#: ../desktopGrid.js:327 ++msgid "Redo" ++msgstr "Refés" ++ ++#: ../desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Mostra l'escriptori al Fitxers" ++ ++#: ../desktopGrid.js:330 ../fileItem.js:612 ++msgid "Open in Terminal" ++msgstr "Obre al Terminal" ++ ++#: ../desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Canvia el fons de l'escriptori…" ++ ++#: ../desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Paràmetres de la pantalla" ++ ++#: ../desktopGrid.js:335 ++msgid "Settings" ++msgstr "Paràmetres" ++ ++#: ../desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Introduïu un nom de fitxer…" ++ ++#: ../desktopGrid.js:586 ++msgid "OK" ++msgstr "D'acord" ++ ++#: ../desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "\tNo s'ha trobat l'ordre" ++ ++#: ../fileItem.js:500 ++msgid "Don’t Allow Launching" ++msgstr "No permetis que s'iniciï" ++ ++#: ../fileItem.js:502 ++msgid "Allow Launching" ++msgstr "Permet que s'iniciï" ++ ++#: ../fileItem.js:580 ++msgid "Open" ++msgstr "Obre" ++ ++#: ../fileItem.js:584 ++msgid "Open With Other Application" ++msgstr "Obre amb una altra aplicació..." ++ ++#: ../fileItem.js:588 ++msgid "Cut" ++msgstr "Retalla" ++ ++#: ../fileItem.js:589 ++msgid "Copy" ++msgstr "Copia" ++ ++#: ../fileItem.js:591 ++msgid "Rename…" ++msgstr "Canvia el nom…" ++ ++#: ../fileItem.js:592 ++msgid "Move to Trash" ++msgstr "Mou a la paperera" ++ ++#: ../fileItem.js:602 ++msgid "Empty Trash" ++msgstr "Buida la paperera" ++ ++#: ../fileItem.js:608 ++msgid "Properties" ++msgstr "Propietats" ++ ++#: ../fileItem.js:610 ++msgid "Show in Files" ++msgstr "Mostra al Fitxers" ++ ++#: ../schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml.h:1 ++msgid "Icon size" ++msgstr "Mida d'icona" ++ ++#: ../schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml.h:2 ++msgid "Set the size for the desktop icons." ++msgstr "Estableix la mida per les icones de l'escriptori." ++ ++#: ../schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml.h:3 ++msgid "Show personal folder" ++msgstr "Mostra la carpeta personal" ++ ++#: ../schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml.h:4 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostra la carpeta personal a l'escriptori." ++ ++#: ../schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml.h:5 ++msgid "Show trash icon" ++msgstr "Mostra la icona de la paperera" ++ ++#: ../schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml.h:6 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostra la icona de la paperera a l'escriptori." ++ + #~ msgid "GNOME Shell Classic" + #~ msgstr "GNOME Shell clàssic" + +diff --git a/po/cs.po b/po/cs.po +index 04bb1956..7ce51c90 100644 +--- a/po/cs.po ++++ b/po/cs.po +@@ -1,11 +1,21 @@ ++# #-#-#-#-# cs.po (gnome-shell-extensions) #-#-#-#-# + # Czech translation for gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # Petr Kovar , 2013. + # Marek Černocký , 2011, 2012, 2013, 2014, 2015, 2017. + # ++# #-#-#-#-# cs.po (desktop-icons master) #-#-#-#-# ++# Czech translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Marek Černocký , 2018. ++# Milan Zink , 2018. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# cs.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -19,6 +29,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + "X-Generator: Gtranslator 2.91.6\n" ++"#-#-#-#-# cs.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:49+0000\n" ++"PO-Revision-Date: 2019-03-02 18:02+0100\n" ++"Last-Translator: Daniel Rusek \n" ++"Language-Team: Czech \n" ++"Language: cs\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -350,3 +374,177 @@ msgstr "Název" + #, javascript-format + msgid "Workspace %d" + msgstr "Pracovní plocha %d" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Název nové složky" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Vytvořit" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Zrušit" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Názvy složek nesmí obsahovat „/“." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Složka se nemůže jmenovat „.“." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Složka se nemůže jmenovat „..“." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Složky s „.“ na začátku jejich názvu jsou skryty." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Soubor nebo složka s tímto názvem již existuje." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Velikost ikon na pracovní ploše" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "malé" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "standardní" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "velké" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Zobrazovat osobní složku na pracovní ploše" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Zobrazovat ikonu koše na pracovní ploše" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nová složka" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Vložit" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Zpět" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Znovu" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Zobrazit plochu v Souborech" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Otevřít v terminálu" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Změnit pozadí…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Zobrazit nastavení" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Nastavení" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Zadejte název souboru…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Budiž" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Nepovolit spouštění" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Povolit spouštění" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Otevřít" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Otevřít pomocí jiné aplikace" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Vyjmout" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopírovat" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Přejmenovat…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Přesunout do koše" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Vyprázdnit koš" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Vlastnosti" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Zobrazit v Souborech" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Velikost ikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Nastavit velikost pro ikony na pracovní ploše." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Zobrazovat osobní složku" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Zobrazovat osobní složku na pracovní ploše." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Zobrazovat koš" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Zobrazovat ikonu koše na pracovní ploše." ++ ++#~ msgid "Huge" ++#~ msgstr "obrovské" ++ ++#~ msgid "Ok" ++#~ msgstr "Ok" +diff --git a/po/da.po b/po/da.po +index 5a4c257c..4e1f110f 100644 +--- a/po/da.po ++++ b/po/da.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# da.po (gnome-shell-extensions master) #-#-#-#-# + # Danish translation for gnome-shell-extensions. + # Copyright (C) 2011-2017 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -6,8 +7,16 @@ + # Ask Hjorth Larsen , 2015, 2017. + # Joe Hansen , 2017. + # ++# #-#-#-#-# da.po (desktop-icons master) #-#-#-#-# ++# Danish translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Alan Mortensen , 2018. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# da.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -20,6 +29,19 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"#-#-#-#-# da.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-04 14:55+0200\n" ++"Last-Translator: scootergrisen\n" ++"Language-Team: Danish \n" ++"Language: da\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -359,3 +381,175 @@ msgstr "Navn" + #, javascript-format + msgid "Workspace %d" + msgstr "Arbejdsområde %d" ++ ++#: createFolderDialog.js:48 ++#| msgid "New Folder" ++msgid "New folder name" ++msgstr "Nyt mappenavn" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Opret" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Annullér" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Mappenavne må ikke indeholde “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "En mappe må ikke kaldes “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "En mappe må ikke kaldes “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mapper med “.” i begyndelsen af deres navn er skjulte." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Der findes allerede en fil eller mappe med det navn." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Størrelsen på skrivebordsikoner" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Små" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Store" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Vis den personlige mappe på skrivebordet" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Vis papirkurvsikonet på skrivebordet" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Ny mappe" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Indsæt" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Fortryd" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Omgør" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Vis skrivebordet i Filer" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Åbn i terminal" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Skift baggrund …" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Skærmindstillinger" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Indstillinger" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Indtast filnavn …" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Tillad ikke opstart" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Tillad opstart" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Åbn" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Åbn med et andet program" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Klip" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopiér" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Omdøb …" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Flyt til papirkurven" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Tøm papirkurven" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Egenskaber" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Vis i Filer" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ikonstørrelse" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Angiv størrelsen på skrivebordsikoner." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Vis personlig mappe" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Vis den personlige mappe på skrivebordet." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Vis papirkurvsikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Vis papirkurvsikonet på skrivebordet." ++ ++#~ msgid "Huge" ++#~ msgstr "Enorme" +diff --git a/po/de.po b/po/de.po +index 01924b87..6bd5c83b 100644 +--- a/po/de.po ++++ b/po/de.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# de.po (gnome-shell-extensions master) #-#-#-#-# + # German translation for gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -7,8 +8,17 @@ + # Wolfgang Stöggl , 2014. + # Paul Seyfert , 2017. + # ++# #-#-#-#-# de.po (desktop-icons master) #-#-#-#-# ++# German translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Mario Blättermann , 2018. ++# rugk , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# de.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -22,6 +32,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.0.2\n" ++"#-#-#-#-# de.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-07 22:46+0000\n" ++"PO-Revision-Date: 2019-03-09 15:42+0100\n" ++"Last-Translator: Tim Sabsch \n" ++"Language-Team: German \n" ++"Language: de\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -366,3 +390,174 @@ msgstr "Name" + #, javascript-format + msgid "Workspace %d" + msgstr "Arbeitsfläche %d" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Neuer Ordner" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Erstellen" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Abbrechen" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Ordnernamen dürfen kein »/« enthalten." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Ein Ordner darf nicht ».« genannt werden." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Ein Ordner darf nicht »..« genannt werden." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Ordner mit ».« am Anfang sind verborgen." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Es gibt bereits eine Datei oder einen Ordner mit diesem Namen." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Größe der Arbeitsflächensymbole" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Klein" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Groß" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Den persönlichen Ordner auf der Arbeitsfläche anzeigen" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Papierkorb-Symbol auf der Arbeitsfläche anzeigen" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Neuer Ordner" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Einfügen" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Rückgängig" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Wiederholen" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Schreibtisch in Dateien anzeigen" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Im Terminal öffnen" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Hintergrund ändern …" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Anzeigeeinstellungen" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Einstellungen" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Dateinamen eingeben …" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "OK" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Start nicht erlauben" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Start erlauben" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Öffnen" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Mit anderer Anwendung öffnen" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Ausschneiden" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopieren" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Umbenennen …" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "In den Papierkorb verschieben" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Papierkorb leeren" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Eigenschaften" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "In Dateiverwaltung anzeigen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Symbolgröße" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Die Größe der Arbeitsflächensymbole festlegen." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Persönlichen Ordner anzeigen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Den persönlichen Ordner auf der Arbeitsfläche anzeigen." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Papierkorb-Symbol anzeigen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Das Papierkorb-Symbol auf der Arbeitsfläche anzeigen." ++ ++#~ msgid "Huge" ++#~ msgstr "Riesig" +diff --git a/po/en_GB.po b/po/en_GB.po +index 92ae445b..60fc687f 100644 +--- a/po/en_GB.po ++++ b/po/en_GB.po +@@ -1,11 +1,20 @@ ++# #-#-#-#-# en_GB.po (gnome-shell-extensions) #-#-#-#-# + # British English translation of gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions'S COPYRIGHT HOLDER. + # This file is distributed under the same license as the gnome-shell-extensions package. + # Bruce Cowan , 2011, 2018. + # Chris Leonard , 2012. + # Philip Withnall , 2014. ++# #-#-#-#-# en_GB.po (desktop-icons master) #-#-#-#-# ++# British English translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Zander Brown , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# en_GB.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/" + "issues\n" +@@ -20,6 +29,20 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.0.6\n" + "X-Project-Style: gnome\n" ++"#-#-#-#-# en_GB.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-08-22 15:53+0000\n" ++"PO-Revision-Date: 2019-08-23 21:48+0100\n" ++"Last-Translator: Zander Brown \n" ++"Language-Team: English - United Kingdom \n" ++"Language: en_GB\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Gtranslator 3.32.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -367,6 +390,178 @@ msgstr "Name" + msgid "Workspace %d" + msgstr "Workspace %d" + ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Icon size" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Display Settings" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Cancel" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "New folder name" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Create" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Folder names cannot contain “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "A folder cannot be called “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "A folder cannot be called “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Folders with “.” at the beginning of their name are hidden." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "There is already a file or folder with that name." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Size for the desktop icons" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Small" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Large" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Show the personal folder on the desktop" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Show the wastebasket icon on the desktop" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "New Folder" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Paste" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Undo" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Redo" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Show Desktop in Files" ++ ++#: desktopGrid.js:330 fileItem.js:626 ++msgid "Open in Terminal" ++msgstr "Open in Terminal" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Change Background…" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Settings" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Enter file name…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Command not found" ++ ++#: fileItem.js:499 ++msgid "Don’t Allow Launching" ++msgstr "Don’t Allow Launching" ++ ++#: fileItem.js:501 ++msgid "Allow Launching" ++msgstr "Allow Launching" ++ ++#: fileItem.js:594 ++msgid "Open" ++msgstr "Open" ++ ++#: fileItem.js:598 ++msgid "Open With Other Application" ++msgstr "Open With Other Application" ++ ++#: fileItem.js:602 ++msgid "Cut" ++msgstr "Cut" ++ ++#: fileItem.js:603 ++msgid "Copy" ++msgstr "Copy" ++ ++#: fileItem.js:605 ++msgid "Rename…" ++msgstr "Rename…" ++ ++#: fileItem.js:606 ++msgid "Move to Trash" ++msgstr "Move to Wastebasket" ++ ++#: fileItem.js:616 ++msgid "Empty Trash" ++msgstr "Empty Wastebasket" ++ ++#: fileItem.js:622 ++msgid "Properties" ++msgstr "Properties" ++ ++#: fileItem.js:624 ++msgid "Show in Files" ++msgstr "Show in Files" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Set the size for the desktop icons." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Show personal folder" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Show the personal folder on the desktop." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Show wastebasket icon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Show the trash icon on the desktop." ++ + #~ msgid "GNOME Shell Classic" + #~ msgstr "GNOME Shell Classic" + +@@ -434,9 +629,6 @@ msgstr "Workspace %d" + #~ "Sets the position of the dock in the screen. Allowed values are 'right' " + #~ "or 'left'" + +-#~ msgid "Icon size" +-#~ msgstr "Icon size" +- + #~ msgid "Sets icon size of the dock." + #~ msgstr "Sets icon size of the dock." + +@@ -508,9 +700,6 @@ msgstr "Workspace %d" + #~ msgid "Display" + #~ msgstr "Display" + +-#~ msgid "Display Settings" +-#~ msgstr "Display Settings" +- + #~ msgid "Do Not Disturb" + #~ msgstr "Do Not Disturb" + +@@ -582,9 +771,6 @@ msgstr "Workspace %d" + #~ msgid "Native" + #~ msgstr "Native" + +-#~ msgid "Cancel" +-#~ msgstr "Cancel" +- + #~ msgid "Ask the user for a default behaviour if true." + #~ msgstr "Ask the user for a default behaviour if true." + +diff --git a/po/es.po b/po/es.po +index a3c0703f..ee30c8ae 100644 +--- a/po/es.po ++++ b/po/es.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# es.po (gnome-shell-extensions master) #-#-#-#-# + # Spanish translation for gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -6,8 +7,18 @@ + # + # Daniel Mustieles , 2011-2015, 2017. + # ++# #-#-#-#-# es.po (1.0) #-#-#-#-# ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR , YEAR. ++# Sergio Costas , 2018. ++# Daniel Mustieles , 2018-2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# es.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -21,6 +32,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Gtranslator 2.91.6\n" ++"#-#-#-#-# es.po (1.0) #-#-#-#-#\n" ++"Project-Id-Version: 1.0\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-05-13 15:13+0200\n" ++"Last-Translator: Daniel Mustieles \n" ++"Language-Team: es \n" ++"Language: es\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Gtranslator 3.32.0\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -361,6 +386,188 @@ msgstr "Nombre" + msgid "Workspace %d" + msgstr "Área de trabajo %d" + ++#: desktopGrid.js:334 ++#, fuzzy ++msgid "Display Settings" ++msgstr "" ++"#-#-#-#-# es.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Configuración de pantalla\n" ++"#-#-#-#-# es.po (1.0) #-#-#-#-#\n" ++"Configuración de pantalla" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++#, fuzzy ++msgid "Icon size" ++msgstr "" ++"#-#-#-#-# es.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Tamaño del icono\n" ++"#-#-#-#-# es.po (1.0) #-#-#-#-#\n" ++"Tamaño de los iconos" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Cancelar" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nombre de la nueva carpeta" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Crear" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Los nombres de carpetas no pueden contener «/»." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Una carpeta no se puede llamar «.»." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Una carpeta no se puede llamar «..»." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Las carpetas cuyo nombre empieza por «.» están ocultas." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Ya hay un archivo o carpeta con ese nombre." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Tamaño de los iconos del escritorio" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Pequeño" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Estándar" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostrar la carpeta personal en el escritorio" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostrar la papelera en el escritorio" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Nueva carpeta" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Pegar" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Deshacer" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Rehacer" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Mostrar el escritorio en Archivos" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Abrir en una terminal" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Cambiar el fondo..." ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Configuración" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Introduzca el nombre del archivo…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "Aceptar" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Comando no encontrado" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "No permitir lanzar" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Permitir lanzar" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Abrir" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Abrir con otra aplicación" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Cortar" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Copiar" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Renombrar…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Mover a la papelera" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Vaciar la papelera" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Propiedades" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Mostrar en Files" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Establece el tamaño de los iconos del escritorio." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostrar la carpeta personal" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostrar la carpeta personal en el escritorio." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostrar la papelera" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostrar la papelera en el escritorio." ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -409,9 +616,6 @@ msgstr "Área de trabajo %d" + #~ msgid "Display" + #~ msgstr "Pantalla" + +-#~ msgid "Display Settings" +-#~ msgstr "Configuración de pantalla" +- + #~ msgid "File System" + #~ msgstr "Sistema de archivos" + +@@ -459,9 +663,6 @@ msgstr "Área de trabajo %d" + #~ "Configura la posición del tablero en la pantalla. Los valores permitidos " + #~ "son «right» (derecha) o «left» (izquierda)" + +-#~ msgid "Icon size" +-#~ msgstr "Tamaño del icono" +- + #~ msgid "Sets icon size of the dock." + #~ msgstr "Configura el tamaño de los íconos del tablero." + +@@ -632,9 +833,6 @@ msgstr "Área de trabajo %d" + #~ msgid "Alt Tab Behaviour" + #~ msgstr "Comportamiento de Alt+Tab" + +-#~ msgid "Cancel" +-#~ msgstr "Cancelar" +- + #~ msgid "Notifications" + #~ msgstr "Notificaciones" + +@@ -668,3 +866,30 @@ msgstr "Área de trabajo %d" + + #~ msgid "Busy" + #~ msgstr "Ocupado" ++ ++#~ msgid "Huge" ++#~ msgstr "Inmenso" ++ ++#~ msgid "Ok" ++#~ msgstr "Aceptar" ++ ++#~ msgid "huge" ++#~ msgstr "inmenso" ++ ++#~ msgid "Maximum width for the icons and filename." ++#~ msgstr "Ancho máximo de los iconos y el nombre de fichero." ++ ++#~ msgid "Shows the Documents folder in the desktop." ++#~ msgstr "Muestra la carpeta Documentos en el escritorio." ++ ++#~ msgid "Shows the Downloads folder in the desktop." ++#~ msgstr "Muestra la carpeta Descargas en el escritorio." ++ ++#~ msgid "Shows the Music folder in the desktop." ++#~ msgstr "Muestra la carpeta Música en el escritorio." ++ ++#~ msgid "Shows the Pictures folder in the desktop." ++#~ msgstr "Muestra la carpeta Imágenes en el escritorio." ++ ++#~ msgid "Shows the Videos folder in the desktop." ++#~ msgstr "Muestra la carpeta Vídeos en el escritorio." +diff --git a/po/fi.po b/po/fi.po +index e0364487..e23c0c85 100644 +--- a/po/fi.po ++++ b/po/fi.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# fi.po (gnome-shell-extensions) #-#-#-#-# + # Finnish translation of gnome-shell-extensions. + # Copyright (C) 2011 Ville-Pekka Vainio + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -7,8 +8,16 @@ + # Ville-Pekka Vainio , 2011. + # Jiri Grönroos , 2012, 2013, 2014, 2015, 2017. + # ++# #-#-#-#-# fi.po (desktop-icons master) #-#-#-#-# ++# Finnish translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Jiri Grönroos , 2018. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# fi.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -24,6 +33,20 @@ msgstr "" + "X-Generator: Gtranslator 2.91.7\n" + "X-Project-Style: gnome\n" + "X-POT-Import-Date: 2012-03-05 15:06:12+0000\n" ++"#-#-#-#-# fi.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-06-02 15:23+0300\n" ++"Last-Translator: Jiri Grönroos \n" ++"Language-Team: Finnish \n" ++"Language: fi\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.0.6\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -352,6 +375,183 @@ msgstr "Nimi" + msgid "Workspace %d" + msgstr "Työtila %d" + ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Näytön asetukset" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++#, fuzzy ++msgid "Icon size" ++msgstr "" ++"#-#-#-#-# fi.po (gnome-shell-extensions) #-#-#-#-#\n" ++"Kuvakkeiden koko\n" ++"#-#-#-#-# fi.po (desktop-icons master) #-#-#-#-#\n" ++"Kuvakekoko" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Uusi kansion nimi" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Luo" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Peru" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Kansion nimi ei voi sisältää merkkiä “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Kansion nimi ei voi olla “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Kansion nimi ei voi olla “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Kansiot, joiden nimi alkaa merkillä “.”, ovat piilotettuja." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Nimi on jo toisen tiedoston tai kansion käytössä." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Työpöytäkuvakkeiden koko" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Pieni" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Normaali" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Suuri" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Näytä kotikansio työpöydällä" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Näytä roskakorin kuvake työpöydällä" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Uusi kansio" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Liitä" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Kumoa" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Tee uudeleen" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Näytä työpöytä tiedostonhallinnassa" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Avaa päätteessä" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Vaihda taustakuvaa…" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Asetukset" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Anna tiedostonimi…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Komentoa ei löydy" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Älä salli käynnistämistä" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Salli käynnistäminen" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Avaa" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Avaa toisella sovelluksella" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Leikkaa" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Kopioi" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Nimeä uudelleen…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Siirrä roskakoriin" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Tyhjennä roskakori" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Ominaisuudet" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Näytä tiedostonhallinnassa" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Aseta työpöytäkuvakkeiden koko." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Näytä kotikansio" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Näytä kotikansio työpöydällä." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Näytä roskakorin kuvake" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Näytä roskakorin kuvake työpöydällä." ++ + #~ msgid "CPU" + #~ msgstr "Suoritin" + +@@ -388,9 +588,6 @@ msgstr "Työtila %d" + #~ msgid "Display" + #~ msgstr "Näyttö" + +-#~ msgid "Display Settings" +-#~ msgstr "Näytön asetukset" +- + #~ msgid "Drag here to add favorites" + #~ msgstr "Raahaa tähän lisätäksesi suosikkeihin" + +@@ -412,9 +609,6 @@ msgstr "Työtila %d" + #~ msgstr "" + #~ "Asettaa telakan sijainnin näytöllä. Sallitut arvot ovat 'right' tai 'left'" + +-#~ msgid "Icon size" +-#~ msgstr "Kuvakkeiden koko" +- + #~ msgid "Sets icon size of the dock." + #~ msgstr "Asettaa telakan kuvakkeiden koon." + +@@ -459,3 +653,6 @@ msgstr "Työtila %d" + + #~ msgid "Workspace & Icons" + #~ msgstr "Työtila ja kuvakkeet" ++ ++#~ msgid "Huge" ++#~ msgstr "Valtava" +diff --git a/po/fr.po b/po/fr.po +index 6825d0dd..6961fa43 100644 +--- a/po/fr.po ++++ b/po/fr.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# fr.po (gnome-shell-extensions master) #-#-#-#-# + # French translation for gnome-shell-extensions. + # Copyright (C) 2011-12 Listed translators + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -5,8 +6,17 @@ + # Alain Lojewski , 2012-2013. + # Charles Monzat , 2018. + # ++# #-#-#-#-# fr.po (desktop-icons master) #-#-#-#-# ++# French translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# ghentdebian , 2018. ++# Charles Monzat , 2018. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# fr.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/" + "issues\n" +@@ -20,6 +30,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n > 1);\n" + "X-Generator: Gtranslator 3.30.0\n" ++"#-#-#-#-# fr.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2018-12-14 09:12+0000\n" ++"PO-Revision-Date: 2018-12-16 17:47+0100\n" ++"Last-Translator: Charles Monzat \n" ++"Language-Team: GNOME French Team \n" ++"Language: fr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1)\n" ++"X-Generator: Gtranslator 3.30.0\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -323,6 +347,146 @@ msgstr "Nom" + msgid "Workspace %d" + msgstr "Espace de travail %d" + ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Taille des icônes du bureau" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Petite" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Normale" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:102 ++msgid "Huge" ++msgstr "Immense" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Montrer le dossier personnel sur le bureau" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Montrer la corbeille sur le bureau" ++ ++#: desktopGrid.js:182 desktopGrid.js:301 ++msgid "New Folder" ++msgstr "Nouveau dossier" ++ ++#: desktopGrid.js:303 ++msgid "Paste" ++msgstr "Coller" ++ ++#: desktopGrid.js:304 ++msgid "Undo" ++msgstr "Annuler" ++ ++#: desktopGrid.js:305 ++msgid "Redo" ++msgstr "Refaire" ++ ++#: desktopGrid.js:307 ++msgid "Open Desktop in Files" ++msgstr "Ouvrir le bureau dans Fichiers" ++ ++#: desktopGrid.js:308 ++msgid "Open Terminal" ++msgstr "Ouvrir un terminal" ++ ++#: desktopGrid.js:310 ++msgid "Change Background…" ++msgstr "Changer l’arrière-plan…" ++ ++#: desktopGrid.js:311 ++msgid "Display Settings" ++msgstr "Configuration d’affichage" ++ ++#: desktopGrid.js:312 ++msgid "Settings" ++msgstr "Paramètres" ++ ++#: desktopGrid.js:568 ++msgid "Enter file name…" ++msgstr "Saisir un nom de fichier…" ++ ++#: desktopGrid.js:572 ++msgid "OK" ++msgstr "Valider" ++ ++#: desktopGrid.js:578 ++msgid "Cancel" ++msgstr "Annuler" ++ ++#: fileItem.js:485 ++msgid "Don’t Allow Launching" ++msgstr "Ne pas autoriser le lancement" ++ ++#: fileItem.js:487 ++msgid "Allow Launching" ++msgstr "Autoriser le lancement" ++ ++#: fileItem.js:550 ++msgid "Open" ++msgstr "Ouvrir" ++ ++#: fileItem.js:553 ++msgid "Cut" ++msgstr "Couper" ++ ++#: fileItem.js:554 ++msgid "Copy" ++msgstr "Copier" ++ ++#: fileItem.js:556 ++msgid "Rename" ++msgstr "Renommer" ++ ++#: fileItem.js:557 ++msgid "Move to Trash" ++msgstr "Mettre à la corbeille" ++ ++#: fileItem.js:567 ++msgid "Empty Trash" ++msgstr "Vider la corbeille" ++ ++#: fileItem.js:573 ++msgid "Properties" ++msgstr "Propriétés" ++ ++#: fileItem.js:575 ++msgid "Show in Files" ++msgstr "Montrer dans Fichiers" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Icon size" ++msgstr "Taille d’icônes" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:13 ++msgid "Set the size for the desktop icons." ++msgstr "Définir la taille des icônes du bureau." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show personal folder" ++msgstr "Montrer le dossier personnel" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:18 ++msgid "Show the personal folder in the desktop." ++msgstr "Montrer le dossier personnel sur le bureau." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show trash icon" ++msgstr "Montrer l’icône de la corbeille" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:23 ++msgid "Show the trash icon in the desktop." ++msgstr "Montrer la corbeille sur le bureau." ++ + #~ msgid "Attach modal dialog to the parent window" + #~ msgstr "Attacher les boîtes de dialogue modales à leur fenêtre parente" + +@@ -360,3 +524,6 @@ msgstr "Espace de travail %d" + + #~ msgid "Memory" + #~ msgstr "Mémoire" ++ ++#~ msgid "Ok" ++#~ msgstr "Valider" +diff --git a/po/fur.po b/po/fur.po +index 0fb3f700..a2793c96 100644 +--- a/po/fur.po ++++ b/po/fur.po +@@ -1,10 +1,19 @@ ++# #-#-#-#-# fur.po (gnome-shell-extensions master) #-#-#-#-# + # Friulian translation for gnome-shell-extensions. + # Copyright (C) 2013 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # Fabio Tomat , 2013. + # ++# #-#-#-#-# fur.po (desktop-icons master) #-#-#-#-# ++# Friulian translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Fabio Tomat , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# fur.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -17,6 +26,19 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "X-Generator: Poedit 1.8.12\n" ++"#-#-#-#-# fur.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-05 22:20+0100\n" ++"Last-Translator: Fabio Tomat \n" ++"Language-Team: Friulian \n" ++"Language: fur\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -355,6 +377,179 @@ msgstr "Non" + msgid "Workspace %d" + msgstr "Spazi di lavôr %d" + ++#: desktopGrid.js:331 ++#, fuzzy ++msgid "Display Settings" ++msgstr "" ++"#-#-#-#-# fur.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Impostazions Visôr\n" ++"#-#-#-#-# fur.po (desktop-icons master) #-#-#-#-#\n" ++"Impostazions visôr" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Gnûf non de cartele" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Cree" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Anule" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "I nons des cartelis no puedin contignî il caratar “/”" ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Une cartele no pues jessi clamade “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Une cartele no pues jessi clamade “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Lis cartelis cul “.” al inizi dal lôr non a son platadis." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Un file o une cartele cul stes non e esist za." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Dimension pes iconis dal scritori" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Piçule" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Largje" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostre la cartele personâl intal scritori" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostre la icone de scovacere intal scritori" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Gnove cartele" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Tache" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Anule" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Torne fâ" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Mostre Scritori in File" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Vierç in Terminâl" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Cambie sfont…" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Impostazions" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Inserìs il non dal file…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Va ben" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "No sta permeti inviament" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Permet inviament" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Vierç" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Vierç cuntune altre aplicazion" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Taie" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Copie" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Cambie non..." ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Sposte te scovacere" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Disvuede scovacere" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Propietâts" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Mostre in File" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Dimension icone" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Stabilìs la dimension pes iconis dal scritori." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostre cartele personâl" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostre la cartele personâl intal scritori." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostre la icone de scovacere" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostre la icone de scovacere intal scritori." ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -381,6 +576,3 @@ msgstr "Spazi di lavôr %d" + + #~ msgid "Display" + #~ msgstr "Visôr" +- +-#~ msgid "Display Settings" +-#~ msgstr "Impostazions Visôr" +diff --git a/po/hr.po b/po/hr.po +index deee76ef..a4d39d14 100644 +--- a/po/hr.po ++++ b/po/hr.po +@@ -1,10 +1,19 @@ ++# #-#-#-#-# hr.po (gnome-shell-extensions master) #-#-#-#-# + # Croatian translation for gnome-shell-extensions. + # Copyright (C) 2017 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # FIRST AUTHOR , YEAR. + # ++# #-#-#-#-# hr.po (gnome-shell-extension-desktop-icons) #-#-#-#-# ++# Croatian translation for gnome-shell-extension-desktop-icons ++# Copyright (c) 2019 Rosetta Contributors and Canonical Ltd 2019 ++# This file is distributed under the same license as the gnome-shell-extension-desktop-icons package. ++# FIRST AUTHOR , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# hr.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -19,6 +28,20 @@ msgstr "" + "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" + "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + "X-Generator: Poedit 2.0.2\n" ++"#-#-#-#-# hr.po (gnome-shell-extension-desktop-icons) #-#-#-#-#\n" ++"Project-Id-Version: gnome-shell-extension-desktop-icons\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-06-22 18:52+0200\n" ++"Last-Translator: gogo \n" ++"Language-Team: Croatian \n" ++"Language: hr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Launchpad-Export-Date: 2019-03-27 09:36+0000\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -353,3 +376,175 @@ msgstr "Naziv" + #, javascript-format + msgid "Workspace %d" + msgstr "Radni prostor %d" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Novi naziv mape" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Stvori" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Odustani" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Naziv mape ne može sadržavati “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Mapa se ne može nazvati “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Mapa se ne može nazvati “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mape sa “.” na početku njihovih naziva su skrivene." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Već postoji datoteka ili mapa s tim nazivom." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Veličina ikona radne površine" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Male" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standardne" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Velike" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Prikaži osobnu mapu na radnoj površini" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Prikaži mapu smeća na radnoj površini" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Nova mapa" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Zalijepi" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Poništi" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Ponovi" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Prikaži radnu površinu u Datotekama" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Otvori u Terminalu" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Promijeni pozadinu…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Postavke zaslona" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Postavke" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Upiši naziv datoteke…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "U redu" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Naredba nije pronađena" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Ne dopuštaj pokretanje" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Dopusti pokretanje" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Otvori" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Otvori s drugom aplikacijom" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Izreži" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Kopiraj" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Preimenuj…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Premjesti u smeće" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Isprazni smeće" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Svojstva" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Prikaži u Datotekama" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Veličina ikona" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Postavi veličinu ikona radne površine." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Prikaži osobnu mapu" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Prikaži osobnu mapu na radnoj površini." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Prikaži ikonu smeća" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Prikaži ikonu smeća na radnoj površini." +diff --git a/po/hu.po b/po/hu.po +index 7c2c406b..06352708 100644 +--- a/po/hu.po ++++ b/po/hu.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# hu.po (gnome-shell-extensions master) #-#-#-#-# + # Hungarian translation of + # Copyright (C) 2011, 2012, 2013, 2014, 2017 Free Software Foundation, Inc. + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -5,8 +6,16 @@ + # Biró Balázs , 2011. + # Gabor Kelemen , 2011, 2012, 2013. + # Balázs Úr , 2013, 2014, 2017. ++# #-#-#-#-# hu.po (desktop-icons master) #-#-#-#-# ++# Hungarian translation for desktop-icons. ++# Copyright (C) 2019 The Free Software Foundation, inc. ++# This file is distributed under the same license as the desktop-icons package. ++# ++# Balázs Úr , 2019. ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# hu.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -20,6 +29,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "X-Generator: Poedit 2.0.2\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"#-#-#-#-# hu.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-06-01 18:50+0200\n" ++"Last-Translator: Balázs Úr \n" ++"Language-Team: Hungarian \n" ++"Language: hu\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Lokalize 18.12.3\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -356,3 +379,175 @@ msgstr "Név" + #, javascript-format + msgid "Workspace %d" + msgstr "%d. munkaterület" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Új mappa neve" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Létrehozás" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Mégse" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "A mappanevek nem tartalmazhatnak „/” karaktert." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Egy mappának nem lehet „.” a neve." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Egy mappának nem lehet „..” a neve." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "A „.” karakterrel kezdődő nevű mappák rejtettek." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Már van egy fájl vagy mappa azzal a névvel." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Az asztali ikonok mérete" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Kicsi" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Szabványos" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Nagy" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "A személyes mappa megjelenítése az asztalon" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "A kuka ikon megjelenítése az asztalon" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Új mappa" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Beillesztés" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Visszavonás" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Újra" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Asztal megjelenítése a Fájlokban" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Megnyitás terminálban" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Háttér megváltoztatása…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Megjelenítés beállításai" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Beállítások" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Adjon meg egy fájlnevet…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "Rendben" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "A parancs nem található" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Ne engedélyezzen indítást" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Indítás engedélyezése" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Megnyitás" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Megnyitás egyéb alkalmazással" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Kivágás" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Másolás" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Átnevezés…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Áthelyezés a Kukába" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Kuka ürítése" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Tulajdonságok" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Megjelenítés a Fájlokban" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ikonméret" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Az asztali ikonok méretének beállítása." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Személyes mappa megjelenítése" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "A személyes mappa megjelenítése az asztalon." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Kuka ikon megjelenítése" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "A kuka ikon megjelenítése az asztalon." +diff --git a/po/id.po b/po/id.po +index 8986a5e7..29f27b6f 100644 +--- a/po/id.po ++++ b/po/id.po +@@ -1,11 +1,20 @@ ++# #-#-#-#-# id.po (gnome-shell-extensions master) #-#-#-#-# + # Indonesian translation for gnome-shell-extensions. + # Copyright (C) 2012 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # + # Andika Triwidada , 2012, 2013. + # Dirgita , 2012. ++# #-#-#-#-# id.po (desktop-icons master) #-#-#-#-# ++# Indonesian translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Kukuh Syafaat , 2018, 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# id.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -20,6 +29,19 @@ msgstr "" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Poedit-SourceCharset: UTF-8\n" + "X-Generator: Poedit 2.0.2\n" ++"#-#-#-#-# id.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-07-11 13:57+0700\n" ++"Last-Translator: Kukuh Syafaat \n" ++"Language-Team: Indonesian \n" ++"Language: id\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Poedit 2.2.3\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -358,8 +380,183 @@ msgstr "Nama" + msgid "Workspace %d" + msgstr "Ruang Kerja %d" + ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nama folder baru" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Buat" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Batal" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Nama folder tak boleh memuat \"/\"." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Sebuah folder tak bisa dinamai \".\"." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Sebuah folder tak bisa dinamai \"..\"." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Folder dengan \".\" di awal nama mereka disembunyikan." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Folder dengan nama itu sudah ada." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Ukuran untuk ikon destop" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Kecil" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standar" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Besar" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Tampilkan folder pribadi di destop" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Tampilkan ikon tong sampah di destop" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Folder Baru" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Tempel" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Tak Jadi" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Jadi Lagi" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Tampilkan Destop pada Berkas" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Buka dalam Terminal" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Ubah Latar Belakang…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Pengaturan Tampilan" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Pengaturan" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Masukkan nama berkas…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Perintah tidak ditemukan" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Jangan Izinkan Peluncuran" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Izinkan Peluncuran" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Buka" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Buka Dengan Aplikasi Lain" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Potong" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Salin" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Ganti Nama…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Pindahkan ke Tong Sampah" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Kosongkan Tong Sampah" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Properti" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Tampilkan pada Berkas" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ukuran ikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Set ukuran untuk ikon destop." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Tampilkan folder pribadi" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Tampilkan folder pribadi di destop." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Tampilkan ikon tong sampah" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Tampilkan ikon tong sampah di destop." ++ + #~ msgid "CPU" + #~ msgstr "CPU" + + #~ msgid "Memory" + #~ msgstr "Memori" ++ ++#~ msgid "Huge" ++#~ msgstr "Sangat besar" +diff --git a/po/it.po b/po/it.po +index 4e3a59c5..2d215b14 100644 +--- a/po/it.po ++++ b/po/it.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# it.po (gnome-shell-extensions) #-#-#-#-# + # Italian translations for GNOME Shell extensions + # Copyright (C) 2011 Giovanni Campagna et al. + # Copyright (C) 2012, 2013, 2014, 2015, 2017 The Free Software Foundation, Inc. +@@ -6,8 +7,17 @@ + # Milo Casagrande , 2013, 2014, 2015, 2017. + # Gianvito Cavasoli , 2017. + # ++# #-#-#-#-# it.po (desktop-icons master) #-#-#-#-# ++# Italian translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Massimo Branchini , 2019. ++# Milo Casagrande , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# it.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -21,6 +31,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 1.8.12\n" ++"#-#-#-#-# it.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-12 09:51+0100\n" ++"Last-Translator: Milo Casagrande \n" ++"Language-Team: Italian \n" ++"Language: it\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -362,3 +386,171 @@ msgstr "Nome" + #, javascript-format + msgid "Workspace %d" + msgstr "Spazio di lavoro %d" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nuova cartella" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Crea" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Annulla" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "I nomi di cartelle non possono contenere il carattere «/»" ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Una cartella non può essere chiamata «.»." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Una cartella non può essere chiamata «..»." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Cartelle il cui nome inizia con «.» sono nascoste." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Esiste già un file o una cartella con quel nome." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Dimensione delle icone della scrivania" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Piccola" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Normale" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostra la cartella personale sulla scrivania" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostra il cestino sulla scrivania" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nuova cartella" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Incolla" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Annulla" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Ripeti" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Mostra la scrivania in File" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Apri in Terminale" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Cambia lo sfondo…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Impostazioni dello schermo" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Impostazioni" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Indicare un nome per il file…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Ok" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Non permettere l'esecuzione" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Permetti l'esecuzione" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Apri" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Apri con altra applicazione" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Taglia" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Copia" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Rinomina…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Sposta nel cestino" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Svuota il cestino" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Proprietà" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Mostra in File" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Dimensione dell'icona" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Imposta la grandezza delle icone della scrivania." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostra la cartella personale" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostra la cartella personale sulla scrivania." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostra il cestino" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostra il cestino sulla scrivania." +diff --git a/po/ja.po b/po/ja.po +index a2201ef1..df5646d2 100644 +--- a/po/ja.po ++++ b/po/ja.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-# + # gnome-shell-extensions ja.po + # Copyright (C) 2011-2013 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -7,8 +8,16 @@ + # Ikuya Awashiro , 2014. + # Hajime Taira , 2014, 2015. + # ++# #-#-#-#-# ja.po (desktop-icons master) #-#-#-#-# ++# Japanese translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# sicklylife , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/" + "issues\n" +@@ -21,6 +30,19 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=1; plural=0;\n" ++"#-#-#-#-# ja.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-08-29 21:30+0900\n" ++"Last-Translator: sicklylife \n" ++"Language-Team: Japanese \n" ++"Language: ja\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=1; plural=0;\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -270,6 +292,188 @@ msgstr "名前" + msgid "Workspace %d" + msgstr "ワークスペース %d" + ++#: desktopGrid.js:334 ++#, fuzzy ++msgid "Display Settings" ++msgstr "" ++"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"ディスプレイ設定\n" ++"#-#-#-#-# ja.po (desktop-icons master) #-#-#-#-#\n" ++"ディスプレイの設定" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++#, fuzzy ++msgid "Icon size" ++msgstr "" ++"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"アイコンのサイズ\n" ++"#-#-#-#-# ja.po (desktop-icons master) #-#-#-#-#\n" ++"アイコンサイズ" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "新しいフォルダー名" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "作成" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "キャンセル" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "“/”は、フォルダー名に含められません。" ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "“.”という名前をフォルダーに付けられません。" ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "“..”という名前をフォルダーに付けられません。" ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "名前が“.”で始まるフォルダーは、隠しフォルダーになります。" ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "その名前のファイルかフォルダーがすでに存在します。" ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "デスクトップアイコンのサイズ" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "小さい" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "標準" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "大きい" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "デスクトップにホームフォルダーを表示する" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "デスクトップにゴミ箱を表示する" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "新しいフォルダー" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "貼り付け" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "元に戻す" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "やり直す" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "“ファイル”でデスクトップを表示" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "端末を開く" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "背景の変更…" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "設定" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "ファイル名を入力してください…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "コマンドが見つかりません" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "起動を許可しない" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "起動を許可する" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "開く" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "別のアプリケーションで開く" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "切り取り" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "コピー" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "名前の変更…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "ゴミ箱へ移動する" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "ゴミ箱を空にする" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "プロパティ" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "“ファイル”で表示" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "デスクトップのアイコンサイズを設定します。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "ホームフォルダーを表示する" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "デスクトップにホームフォルダーを表示します。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "ゴミ箱アイコンを表示する" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "デスクトップにゴミ箱のアイコンを表示します。" ++ + #~ msgid "Attach modal dialog to the parent window" + #~ msgstr "モーダルダイアログを親ウィンドウに結び付ける" + +@@ -365,9 +569,6 @@ msgstr "ワークスペース %d" + #~ msgid "Display" + #~ msgstr "ディスプレイ" + +-#~ msgid "Display Settings" +-#~ msgstr "ディスプレイ設定" +- + #~ msgid "Suspend" + #~ msgstr "サスペンド" + +@@ -413,9 +614,6 @@ msgstr "ワークスペース %d" + #~ msgid "Remove from Favorites" + #~ msgstr "お気に入りから削除" + +-#~ msgid "Icon size" +-#~ msgstr "アイコンのサイズ" +- + #~ msgid "Position of the dock" + #~ msgstr "ドックの位置" + +diff --git a/po/nl.po b/po/nl.po +index a7998d33..bbf7b1f4 100644 +--- a/po/nl.po ++++ b/po/nl.po +@@ -1,11 +1,20 @@ ++# #-#-#-#-# nl.po (gnome-shell-extensions master) #-#-#-#-# + # Dutch translation for gnome-shell-extensions. + # Copyright (C) 2013 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # Reinout van Schouwen , 2013, 2014. + # Nathan Follens , 2015-2017. + # Hannie Dumoleyn , 2015. ++# #-#-#-#-# nl.po (desktop-icons master) #-#-#-#-# ++# Dutch translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Nathan Follens , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# nl.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -20,6 +29,20 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n != 1);\n" + "X-Generator: Poedit 2.0.2\n" + "X-Project-Style: gnome\n" ++"#-#-#-#-# nl.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-01 12:11+0000\n" ++"PO-Revision-Date: 2019-03-04 19:46+0100\n" ++"Last-Translator: Nathan Follens \n" ++"Language-Team: Dutch \n" ++"Language: nl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.1\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -360,6 +383,174 @@ msgstr "Naam" + msgid "Workspace %d" + msgstr "Werkblad %d" + ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nieuwe mapnaam" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Aanmaken" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "Annuleren" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Mapnamen kunnen geen ‘/’ bevatten." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Een map kan niet ‘.’ worden genoemd." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Een map kan niet ‘..’ worden genoemd." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mappen waarvan de naam begint met ‘.’ zijn verborgen." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Er bestaat al een bestand of map met die naam." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Grootte van bureaubladpictogrammen" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Klein" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standaard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Groot" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Toon de persoonlijke map op het bureaublad" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Toon het prullenbakpictogram op het bureaublad" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Nieuwe map" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Plakken" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Ongedaan maken" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Opnieuw" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Bureaublad tonen in Bestanden" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Openen in terminalvenster" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Achtergrond aanpassen…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Scherminstellingen" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Instellingen" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Voer bestandsnaam in…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Oké" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Toepassingen starten niet toestaan" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Toepassingen starten toestaan" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Openen" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Met andere toepassing openen" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Knippen" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopiëren" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Hernoemen…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Verplaatsen naar prullenbak" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Prullenbak legen" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Eigenschappen" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Tonen in Bestanden" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Pictogramgrootte" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Stel de grootte van de bureaubladpictogrammen in." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Persoonlijke map tonen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Toon de persoonlijke map op het bureaublad." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Prullenbakpictogram tonen" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Toon het prullenbakpictogram op het bureaublad." ++ + #~ msgid "GNOME Shell Classic" + #~ msgstr "Gnome Shell klassiek" + +diff --git a/po/pl.po b/po/pl.po +index 35799eef..a779932a 100644 +--- a/po/pl.po ++++ b/po/pl.po +@@ -1,11 +1,21 @@ ++# #-#-#-#-# pl.po (gnome-shell-extensions) #-#-#-#-# + # Polish translation for gnome-shell-extensions. + # Copyright © 2011-2017 the gnome-shell-extensions authors. + # This file is distributed under the same license as the gnome-shell-extensions package. + # Piotr Drąg , 2011-2017. + # Aviary.pl , 2011-2017. + # ++# #-#-#-#-# pl.po (desktop-icons) #-#-#-#-# ++# Polish translation for desktop-icons. ++# Copyright © 2018-2019 the desktop-icons authors. ++# This file is distributed under the same license as the desktop-icons package. ++# Piotr Drąg , 2018-2019. ++# Aviary.pl , 2018-2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# pl.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -19,6 +29,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " + "|| n%100>=20) ? 1 : 2);\n" ++"#-#-#-#-# pl.po (desktop-icons) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-05-01 13:03+0200\n" ++"Last-Translator: Piotr Drąg \n" ++"Language-Team: Polish \n" ++"Language: pl\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " ++"|| n%100>=20) ? 1 : 2);\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -358,3 +382,175 @@ msgstr "Nazwa" + #, javascript-format + msgid "Workspace %d" + msgstr "%d. obszar roboczy" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nazwa nowego katalogu" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Utwórz" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Anuluj" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Nazwy katalogów nie mogą zawierać znaku „/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Katalog nie może mieć nazwy „.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Katalog nie może mieć nazwy „..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Katalogi z „.” na początku nazwy są ukryte." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Plik lub katalog o tej nazwie już istnieje." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Rozmiar ikon na pulpicie" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Mały" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standardowy" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Duży" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Katalog domowy na pulpicie" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Kosz na pulpicie" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Nowy katalog" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Wklej" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Cofnij" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Ponów" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Wyświetl pulpit w menedżerze plików" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Otwórz w terminalu" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Zmień tło…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Ustawienia ekranu" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Ustawienia" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Nazwa pliku…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Nie odnaleziono polecenia" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Nie zezwalaj na uruchamianie" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Zezwól na uruchamianie" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Otwórz" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Otwórz za pomocą innego programu" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Wytnij" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Skopiuj" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Zmień nazwę…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Przenieś do kosza" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Opróżnij kosz" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Właściwości" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Wyświetl w menedżerze plików" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Rozmiar ikon" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Ustawia rozmiar ikon na pulpicie." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Katalog domowy" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Wyświetla katalog domowy na pulpicie." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Kosz" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Wyświetla kosz na pulpicie." +diff --git a/po/pt_BR.po b/po/pt_BR.po +index d029648d..f1e17f73 100644 +--- a/po/pt_BR.po ++++ b/po/pt_BR.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# pt_BR.po (gnome-shell-extensions master) #-#-#-#-# + # Brazilian Portuguese translation for gnome-shell-extensions. + # Copyright (C) 2017 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -9,8 +10,17 @@ + # Og Maciel , 2012. + # Enrico Nicoletto , 2013, 2014. + # Rafael Fontenelle , 2013, 2017. ++# #-#-#-#-# pt_BR.po (desktop-icons master) #-#-#-#-# ++# Brazilian Portuguese translation for desktop-icons. ++# Copyright (C) 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Enrico Nicoletto , 2018. ++# Rafael Fontenelle , 2018-2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# pt_BR.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -25,6 +35,20 @@ msgstr "" + "Plural-Forms: nplurals=2; plural=(n > 1);\n" + "X-Generator: Virtaal 1.0.0-beta1\n" + "X-Project-Style: gnome\n" ++"#-#-#-#-# pt_BR.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-04-29 17:35-0300\n" ++"Last-Translator: Rafael Fontenelle \n" ++"Language-Team: Brazilian Portuguese \n" ++"Language: pt_BR\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n > 1)\n" ++"X-Generator: Gtranslator 3.32.0\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -366,6 +390,183 @@ msgstr "Nome" + msgid "Workspace %d" + msgstr "Espaço de trabalho %d" + ++#: desktopGrid.js:334 ++#, fuzzy ++msgid "Display Settings" ++msgstr "" ++"#-#-#-#-# pt_BR.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Configurações de tela\n" ++"#-#-#-#-# pt_BR.po (desktop-icons master) #-#-#-#-#\n" ++"Configurações de exibição" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Tamanho do ícone" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Cancelar" ++ ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nome da nova pasta" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Criar" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Nomes de pastas não podem conter “/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Uma pasta não pode ser chamada “.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Uma pasta não pode ser chamada “..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Pastas com “.” no começo de seus nomes são ocultas." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Já existe um arquivo ou uma pasta com esse nome." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Tamanho para os ícones da área de trabalho" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Pequeno" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Padrão" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Grande" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Mostrar a pasta pessoal na área de trabalho" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Mostrar o ícone da lixeira na área de trabalho" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Nova pasta" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Colar" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Desfazer" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Refazer" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Mostrar a área de trabalho no Arquivos" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Abrir no terminal" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Alterar plano de fundo…" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Configurações" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Insira um nome de arquivo…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Comando não encontrado" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Não permitir iniciar" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Permitir iniciar" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Abrir" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Abrir com outro aplicativo" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Recortar" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Copiar" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Renomear…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Mover para a lixeira" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Esvaziar lixeira" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Propriedades" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Mostrar no Arquivos" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Define o tamanho para os ícones da área de trabalho." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Mostrar pasta pessoal" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Mostra a pasta pessoal na área de trabalho." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Mostrar ícone da lixeira" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Mostra o ícone da lixeira na área de trabalho." ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -414,9 +615,6 @@ msgstr "Espaço de trabalho %d" + #~ msgid "Display" + #~ msgstr "Tela" + +-#~ msgid "Display Settings" +-#~ msgstr "Configurações de tela" +- + #~ msgid "The application icon mode." + #~ msgstr "O modo de ícone do aplicativo." + +@@ -451,9 +649,6 @@ msgstr "Espaço de trabalho %d" + #~ "Define a posição do dock na tela. Os valores permitidos são \"right\" ou " + #~ "\"left\"" + +-#~ msgid "Icon size" +-#~ msgstr "Tamanho do ícone" +- + #~ msgid "Sets icon size of the dock." + #~ msgstr "Define o tamanho do ícone do dock." + +@@ -613,9 +808,6 @@ msgstr "Espaço de trabalho %d" + #~ msgid "Alt Tab Behaviour" + #~ msgstr "Comportamento do Alt Tab" + +-#~ msgid "Cancel" +-#~ msgstr "Cancelar" +- + #~ msgid "Ask the user for a default behaviour if true." + #~ msgstr "Pergunte ao usuário por um comportamento padrão se marcado." + +@@ -639,3 +831,9 @@ msgstr "Espaço de trabalho %d" + + #~ msgid "Log Out..." + #~ msgstr "Encerrar sessão..." ++ ++#~ msgid "Huge" ++#~ msgstr "Enorme" ++ ++#~ msgid "Ok" ++#~ msgstr "Ok" +diff --git a/po/ru.po b/po/ru.po +index c18c0baa..9320c3ca 100644 +--- a/po/ru.po ++++ b/po/ru.po +@@ -1,11 +1,20 @@ ++# #-#-#-#-# ru.po (gnome-shell-extensions gnome-3-0) #-#-#-#-# + # Russian translation for gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # Yuri Myasoedov , 2011, 2012, 2013. + # Stas Solovey , 2011, 2012, 2013, 2015, 2017. + # ++# #-#-#-#-# ru.po #-#-#-#-# ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# Eaglers , 2018. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# ru.po (gnome-shell-extensions gnome-3-0) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions gnome-3-0\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -20,6 +29,21 @@ msgstr "" + "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" + "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + "X-Generator: Poedit 2.0.3\n" ++"#-#-#-#-# ru.po #-#-#-#-#\n" ++"Project-Id-Version: \n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2018-11-22 08:42+0000\n" ++"PO-Revision-Date: 2018-11-22 22:02+0300\n" ++"Last-Translator: Stas Solovey \n" ++"Language-Team: Russian \n" ++"Language: ru\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" ++"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++"X-Generator: Poedit 2.2\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -360,6 +384,138 @@ msgstr "Название" + msgid "Workspace %d" + msgstr "Рабочая область %d" + ++#: prefs.js:89 ++msgid "Size for the desktop icons" ++msgstr "Размер значков" ++ ++#: prefs.js:89 ++msgid "Small" ++msgstr "Маленький" ++ ++#: prefs.js:89 ++msgid "Standard" ++msgstr "Стандартный" ++ ++#: prefs.js:89 ++msgid "Large" ++msgstr "Большой" ++ ++#: prefs.js:89 ++msgid "Huge" ++msgstr "Огромный" ++ ++#: prefs.js:90 ++msgid "Show the personal folder in the desktop" ++msgstr "Показывать домашнюю папку на рабочем столе" ++ ++#: prefs.js:91 ++msgid "Show the trash icon in the desktop" ++msgstr "Показывать «Корзину» на рабочем столе" ++ ++#: desktopGrid.js:185 desktopGrid.js:304 ++msgid "New Folder" ++msgstr "Создать папку" ++ ++#: desktopGrid.js:306 ++msgid "Paste" ++msgstr "Вставить" ++ ++#: desktopGrid.js:307 ++msgid "Undo" ++msgstr "Отменить" ++ ++#: desktopGrid.js:308 ++msgid "Redo" ++msgstr "Повторить" ++ ++#: desktopGrid.js:310 ++msgid "Open Desktop in Files" ++msgstr "Открыть «Рабочий стол» в «Файлах»" ++ ++#: desktopGrid.js:311 ++msgid "Open Terminal" ++msgstr "Открыть терминал" ++ ++#: desktopGrid.js:313 ++msgid "Change Background…" ++msgstr "Изменить фон…" ++ ++#: desktopGrid.js:314 ++msgid "Display Settings" ++msgstr "Настройки дисплея" ++ ++#: desktopGrid.js:315 ++msgid "Settings" ++msgstr "Параметры" ++ ++#: desktopGrid.js:569 ++msgid "Enter file name…" ++msgstr "Ввести имя файла…" ++ ++#: desktopGrid.js:573 ++msgid "Ok" ++msgstr "ОК" ++ ++#: desktopGrid.js:579 ++msgid "Cancel" ++msgstr "Отмена" ++ ++#: fileItem.js:390 ++msgid "Open" ++msgstr "Открыть" ++ ++#: fileItem.js:393 ++msgid "Cut" ++msgstr "Вырезать" ++ ++#: fileItem.js:394 ++msgid "Copy" ++msgstr "Вставить" ++ ++#: fileItem.js:395 ++msgid "Rename" ++msgstr "Переименовать" ++ ++#: fileItem.js:396 ++msgid "Move to Trash" ++msgstr "Переместить в корзину" ++ ++#: fileItem.js:400 ++msgid "Empty trash" ++msgstr "Очистить корзину" ++ ++#: fileItem.js:406 ++msgid "Properties" ++msgstr "Свойства" ++ ++#: fileItem.js:408 ++msgid "Show in Files" ++msgstr "Показать в «Файлах»" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Icon size" ++msgstr "Размер значков" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:13 ++msgid "Set the size for the desktop icons." ++msgstr "Установить размер значков на рабочем столе." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show personal folder" ++msgstr "Показывать домашнюю папку" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:18 ++msgid "Show the personal folder in the desktop." ++msgstr "Показывать значок домашней папки на рабочем столе." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show trash icon" ++msgstr "Показывать значок корзины" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:23 ++msgid "Show the trash icon in the desktop." ++msgstr "Показывать значок корзины на рабочем столе." ++ + #~ msgid "CPU" + #~ msgstr "ЦП" + +diff --git a/po/sv.po b/po/sv.po +index 3aeafaca..33eba9f4 100644 +--- a/po/sv.po ++++ b/po/sv.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# sv.po (gnome-shell-extensions) #-#-#-#-# + # Swedish translation for gnome-shell-extensions. + # Copyright © 2011, 2012, 2014, 2015, 2017 Free Software Foundation, Inc. + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -5,8 +6,17 @@ + # Mattias Eriksson , 2014. + # Anders Jonsson , 2015, 2017. + # ++# #-#-#-#-# sv.po (desktop-icons master) #-#-#-#-# ++# Swedish translation for desktop-icons. ++# Copyright © 2018, 2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Anders Jonsson , 2018, 2019. ++# Josef Andersson , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# sv.po (gnome-shell-extensions) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -19,6 +29,20 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "X-Generator: Poedit 2.0.4\n" ++"#-#-#-#-# sv.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-04-29 14:11+0000\n" ++"PO-Revision-Date: 2019-08-22 17:52+0200\n" ++"Last-Translator: Anders Jonsson \n" ++"Language-Team: Swedish \n" ++"Language: sv\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Poedit 2.2.3\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -355,8 +379,188 @@ msgstr "Namn" + msgid "Workspace %d" + msgstr "Arbetsyta %d" + ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Nytt mappnamn" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Skapa" ++ ++#: createFolderDialog.js:74 desktopGrid.js:592 ++msgid "Cancel" ++msgstr "Avbryt" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Mappnamn kan inte innehålla ”/”." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "En mapp kan inte kallas ”.”." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "En mapp kan inte kallas ”..”." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Mappar med ”.” i början på sitt namn är dolda." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Det finns redan en fil eller mapp med det namnet" ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Storlek för skrivbordsikonerna" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Liten" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standard" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Stor" ++ ++# TODO: *ON* the desktop? ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Visa den personliga mappen på skrivbordet" ++ ++# TODO: *ON* the desktop? ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Visa papperskorgsikonen på skrivbordet" ++ ++#: desktopGrid.js:323 ++msgid "New Folder" ++msgstr "Ny mapp" ++ ++#: desktopGrid.js:325 ++msgid "Paste" ++msgstr "Klistra in" ++ ++#: desktopGrid.js:326 ++msgid "Undo" ++msgstr "Ångra" ++ ++#: desktopGrid.js:327 ++msgid "Redo" ++msgstr "Gör om" ++ ++#: desktopGrid.js:329 ++msgid "Show Desktop in Files" ++msgstr "Visa skrivbord i Filer" ++ ++#: desktopGrid.js:330 fileItem.js:610 ++msgid "Open in Terminal" ++msgstr "Öppna i terminal" ++ ++#: desktopGrid.js:332 ++msgid "Change Background…" ++msgstr "Ändra bakgrund…" ++ ++#: desktopGrid.js:334 ++msgid "Display Settings" ++msgstr "Visningsinställningar" ++ ++#: desktopGrid.js:335 ++msgid "Settings" ++msgstr "Inställningar" ++ ++#: desktopGrid.js:582 ++msgid "Enter file name…" ++msgstr "Ange filnamn…" ++ ++#: desktopGrid.js:586 ++msgid "OK" ++msgstr "OK" ++ ++#: desktopIconsUtil.js:61 ++msgid "Command not found" ++msgstr "Kommandot hittades inte" ++ ++#: fileItem.js:494 ++msgid "Don’t Allow Launching" ++msgstr "Tillåt ej programstart" ++ ++#: fileItem.js:496 ++msgid "Allow Launching" ++msgstr "Tillåt programstart" ++ ++#: fileItem.js:578 ++msgid "Open" ++msgstr "Öppna" ++ ++#: fileItem.js:582 ++msgid "Open With Other Application" ++msgstr "Öppna med annat program" ++ ++#: fileItem.js:586 ++msgid "Cut" ++msgstr "Klipp ut" ++ ++#: fileItem.js:587 ++msgid "Copy" ++msgstr "Kopiera" ++ ++#: fileItem.js:589 ++msgid "Rename…" ++msgstr "Byt namn…" ++ ++#: fileItem.js:590 ++msgid "Move to Trash" ++msgstr "Flytta till papperskorgen" ++ ++#: fileItem.js:600 ++msgid "Empty Trash" ++msgstr "Töm papperskorgen" ++ ++#: fileItem.js:606 ++msgid "Properties" ++msgstr "Egenskaper" ++ ++#: fileItem.js:608 ++msgid "Show in Files" ++msgstr "Visa i Filer" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Ikonstorlek" ++ ++# TODO: *ON* the desktop? ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Ställ in storleken för skrivbordsikonerna." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Visa personlig mapp" ++ ++# TODO: *ON* the desktop? ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Visa den personliga mappen på skrivbordet." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Visa papperskorgsikon" ++ ++# TODO: *ON* the desktop? ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Visa papperskorgsikonen på skrivbordet." ++ + #~ msgid "CPU" + #~ msgstr "CPU" + + #~ msgid "Memory" + #~ msgstr "Minne" ++ ++#~ msgid "Huge" ++#~ msgstr "Enorm" +diff --git a/po/tr.po b/po/tr.po +index 6243374b..30ceafa0 100644 +--- a/po/tr.po ++++ b/po/tr.po +@@ -1,3 +1,4 @@ ++# #-#-#-#-# tr.po (gnome-shell-extensions master) #-#-#-#-# + # Turkish translation for gnome-shell-extensions. + # Copyright (C) 2012 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. +@@ -7,8 +8,19 @@ + # Muhammet Kara , 2013, 2014, 2015. + # Furkan Tokaç , 2017. + # ++# #-#-#-#-# tr.po #-#-#-#-# ++# Turkish translation for desktop-icons. ++# Copyright (C) 2000-2019 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# ++# Sabri Ünal , 2019. ++# Serdar Sağlam , 2019 ++# Emin Tufan Çetin , 2019. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# tr.po (gnome-shell-extensions master) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions master\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -22,6 +34,20 @@ msgstr "" + "Content-Transfer-Encoding: 8bit\n" + "Plural-Forms: nplurals=1; plural=0;\n" + "X-Generator: Gtranslator 2.91.7\n" ++"#-#-#-#-# tr.po #-#-#-#-#\n" ++"Project-Id-Version: \n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2019-03-09 14:47+0000\n" ++"PO-Revision-Date: 2019-03-13 13:43+0300\n" ++"Last-Translator: Emin Tufan Çetin \n" ++"Language-Team: Türkçe \n" ++"Language: tr\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"X-Generator: Gtranslator 3.30.1\n" ++"Plural-Forms: nplurals=1; plural=0;\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -362,6 +388,174 @@ msgstr "İsim" + msgid "Workspace %d" + msgstr "Çalışma Alanı %d" + ++#: createFolderDialog.js:48 ++msgid "New folder name" ++msgstr "Yeni klasör adı" ++ ++#: createFolderDialog.js:72 ++msgid "Create" ++msgstr "Oluştur" ++ ++#: createFolderDialog.js:74 desktopGrid.js:586 ++msgid "Cancel" ++msgstr "İptal" ++ ++#: createFolderDialog.js:145 ++msgid "Folder names cannot contain “/”." ++msgstr "Klasör adları “/” içeremez." ++ ++#: createFolderDialog.js:148 ++msgid "A folder cannot be called “.”." ++msgstr "Bir klasör “.” olarak adlandırılamaz." ++ ++#: createFolderDialog.js:151 ++msgid "A folder cannot be called “..”." ++msgstr "Bir klasör “..” olarak adlandırılamaz." ++ ++#: createFolderDialog.js:153 ++msgid "Folders with “.” at the beginning of their name are hidden." ++msgstr "Adlarının başında “.” bulunan klasörler gizlenir." ++ ++#: createFolderDialog.js:155 ++msgid "There is already a file or folder with that name." ++msgstr "Zaten bu adda bir dosya veya klasör var." ++ ++#: prefs.js:102 ++msgid "Size for the desktop icons" ++msgstr "Masaüstü simgeleri boyutu" ++ ++#: prefs.js:102 ++msgid "Small" ++msgstr "Küçük" ++ ++#: prefs.js:102 ++msgid "Standard" ++msgstr "Standart" ++ ++#: prefs.js:102 ++msgid "Large" ++msgstr "Büyük" ++ ++#: prefs.js:103 ++msgid "Show the personal folder in the desktop" ++msgstr "Kişisel klasörü masaüstünde göster" ++ ++#: prefs.js:104 ++msgid "Show the trash icon in the desktop" ++msgstr "Çöp kutusunu masaüstünde göster" ++ ++#: desktopGrid.js:320 ++msgid "New Folder" ++msgstr "Yeni Klasör" ++ ++#: desktopGrid.js:322 ++msgid "Paste" ++msgstr "Yapıştır" ++ ++#: desktopGrid.js:323 ++msgid "Undo" ++msgstr "Geri Al" ++ ++#: desktopGrid.js:324 ++msgid "Redo" ++msgstr "Yinele" ++ ++#: desktopGrid.js:326 ++msgid "Show Desktop in Files" ++msgstr "Masaüstünü Dosyalarʼda Göster" ++ ++#: desktopGrid.js:327 fileItem.js:606 ++msgid "Open in Terminal" ++msgstr "Uçbirimde Aç" ++ ++#: desktopGrid.js:329 ++msgid "Change Background…" ++msgstr "Arka Planı Değiştir…" ++ ++#: desktopGrid.js:331 ++msgid "Display Settings" ++msgstr "Görüntü Ayarları" ++ ++#: desktopGrid.js:332 ++msgid "Settings" ++msgstr "Ayarlar" ++ ++#: desktopGrid.js:576 ++msgid "Enter file name…" ++msgstr "Dosya adını gir…" ++ ++#: desktopGrid.js:580 ++msgid "OK" ++msgstr "Tamam" ++ ++#: fileItem.js:490 ++msgid "Don’t Allow Launching" ++msgstr "Başlatmaya İzin Verme" ++ ++#: fileItem.js:492 ++msgid "Allow Launching" ++msgstr "Başlatmaya İzin Ver" ++ ++#: fileItem.js:574 ++msgid "Open" ++msgstr "Aç" ++ ++#: fileItem.js:578 ++msgid "Open With Other Application" ++msgstr "Başka Uygulamayla Aç" ++ ++#: fileItem.js:582 ++msgid "Cut" ++msgstr "Kes" ++ ++#: fileItem.js:583 ++msgid "Copy" ++msgstr "Kopyala" ++ ++#: fileItem.js:585 ++msgid "Rename…" ++msgstr "Yeniden Adlandır…" ++ ++#: fileItem.js:586 ++msgid "Move to Trash" ++msgstr "Çöpe Taşı" ++ ++#: fileItem.js:596 ++msgid "Empty Trash" ++msgstr "Çöpü Boşalt" ++ ++#: fileItem.js:602 ++msgid "Properties" ++msgstr "Özellikler" ++ ++#: fileItem.js:604 ++msgid "Show in Files" ++msgstr "Dosyalarʼda Göster" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:11 ++msgid "Icon size" ++msgstr "Simge boyutu" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Set the size for the desktop icons." ++msgstr "Masaüstü simgelerinin boyutunu ayarla." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:16 ++msgid "Show personal folder" ++msgstr "Kişisel klasörü göster" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show the personal folder in the desktop." ++msgstr "Kişisel klasörü masaüstünde göster." ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:21 ++msgid "Show trash icon" ++msgstr "Çöp kutusunu göster" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show the trash icon in the desktop." ++msgstr "Çöp kutusu simgesini masaüstünde göster." ++ + #~ msgid "CPU" + #~ msgstr "İşlemci" + +diff --git a/po/zh_TW.po b/po/zh_TW.po +index 74a95f8a..fa5ba9b8 100644 +--- a/po/zh_TW.po ++++ b/po/zh_TW.po +@@ -1,10 +1,19 @@ ++# #-#-#-#-# zh_TW.po (gnome-shell-extensions gnome-3-0) #-#-#-#-# + # Chinese (Taiwan) translation for gnome-shell-extensions. + # Copyright (C) 2011 gnome-shell-extensions's COPYRIGHT HOLDER + # This file is distributed under the same license as the gnome-shell-extensions package. + # Cheng-Chia Tseng , 2011. + # ++# #-#-#-#-# zh_TW.po (desktop-icons master) #-#-#-#-# ++# Chinese (Taiwan) translation for desktop-icons. ++# Copyright (C) 2018 desktop-icons's COPYRIGHT HOLDER ++# This file is distributed under the same license as the desktop-icons package. ++# Yi-Jyun Pan , 2018. ++# ++#, fuzzy + msgid "" + msgstr "" ++"#-#-#-#-# zh_TW.po (gnome-shell-extensions gnome-3-0) #-#-#-#-#\n" + "Project-Id-Version: gnome-shell-extensions gnome-3-0\n" + "Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" + "shell&keywords=I18N+L10N&component=extensions\n" +@@ -17,6 +26,19 @@ msgstr "" + "Content-Type: text/plain; charset=UTF-8\n" + "Content-Transfer-Encoding: 8bit\n" + "X-Generator: Poedit 2.0.3\n" ++"#-#-#-#-# zh_TW.po (desktop-icons master) #-#-#-#-#\n" ++"Project-Id-Version: desktop-icons master\n" ++"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/ShellExtensions/desktop-" ++"icons/issues\n" ++"POT-Creation-Date: 2018-10-22 14:12+0000\n" ++"PO-Revision-Date: 2018-10-24 21:31+0800\n" ++"Language-Team: Chinese (Taiwan) \n" ++"Language: zh_TW\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Last-Translator: pan93412 \n" ++"X-Generator: Poedit 2.2\n" + + #: data/gnome-classic.desktop.in:3 data/gnome-classic.session.desktop.in:3 + msgid "GNOME Classic" +@@ -344,6 +366,127 @@ msgstr "名稱" + msgid "Workspace %d" + msgstr "工作區 %d" + ++#: desktopGrid.js:307 ++#, fuzzy ++msgid "Display Settings" ++msgstr "" ++"#-#-#-#-# zh_TW.po (gnome-shell-extensions gnome-3-0) #-#-#-#-#\n" ++"顯示設定值\n" ++"#-#-#-#-# zh_TW.po (desktop-icons master) #-#-#-#-#\n" ++"顯示設定" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:12 ++msgid "Icon size" ++msgstr "圖示大小" ++ ++#: prefs.js:89 ++msgid "Size for the desktop icons" ++msgstr "桌面圖示的大小" ++ ++#: prefs.js:89 ++msgid "Small" ++msgstr "小圖示" ++ ++#: prefs.js:89 ++msgid "Standard" ++msgstr "標準大小圖示" ++ ++#: prefs.js:89 ++msgid "Large" ++msgstr "大圖示" ++ ++#: prefs.js:89 ++msgid "Huge" ++msgstr "巨大圖示" ++ ++#: prefs.js:90 ++msgid "Show the personal folder in the desktop" ++msgstr "在桌面顯示個人資料夾" ++ ++#: prefs.js:91 ++msgid "Show the trash icon in the desktop" ++msgstr "在桌面顯示垃圾桶圖示" ++ ++#: desktopGrid.js:178 desktopGrid.js:297 ++msgid "New Folder" ++msgstr "新增資料夾" ++ ++#: desktopGrid.js:299 ++msgid "Paste" ++msgstr "貼上" ++ ++#: desktopGrid.js:300 ++msgid "Undo" ++msgstr "復原" ++ ++#: desktopGrid.js:301 ++msgid "Redo" ++msgstr "重做" ++ ++#: desktopGrid.js:303 ++msgid "Open Desktop in Files" ++msgstr "在《檔案》中開啟桌面" ++ ++#: desktopGrid.js:304 ++msgid "Open Terminal" ++msgstr "開啟終端器" ++ ++#: desktopGrid.js:306 ++msgid "Change Background…" ++msgstr "變更背景圖片…" ++ ++#: desktopGrid.js:308 ++msgid "Settings" ++msgstr "設定" ++ ++#: fileItem.js:223 ++msgid "Open" ++msgstr "開啟" ++ ++#: fileItem.js:226 ++msgid "Cut" ++msgstr "剪下" ++ ++#: fileItem.js:227 ++msgid "Copy" ++msgstr "複製" ++ ++#: fileItem.js:228 ++msgid "Move to Trash" ++msgstr "移動到垃圾桶" ++ ++#: fileItem.js:232 ++msgid "Empty trash" ++msgstr "清空回收桶" ++ ++#: fileItem.js:238 ++msgid "Properties" ++msgstr "屬性" ++ ++#: fileItem.js:240 ++msgid "Show in Files" ++msgstr "在《檔案》中顯示" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:13 ++msgid "Set the size for the desktop icons." ++msgstr "設定桌面圖示的大小。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:17 ++msgid "Show personal folder" ++msgstr "顯示個人資料夾" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:18 ++msgid "Show the personal folder in the desktop." ++msgstr "在桌面顯示個人資料夾。" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 ++msgid "Show trash icon" ++msgstr "顯示垃圾桶圖示" ++ ++#: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:23 ++msgid "Show the trash icon in the desktop." ++msgstr "在桌面顯示垃圾桶圖示。" ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -371,9 +514,6 @@ msgstr "工作區 %d" + #~ msgid "Display" + #~ msgstr "顯示" + +-#~ msgid "Display Settings" +-#~ msgstr "顯示設定值" +- + #~ msgid "Suspend" + #~ msgstr "暫停" + +@@ -481,9 +621,6 @@ msgstr "工作區 %d" + #~ msgid "Enable/disable autohide" + #~ msgstr "啟用/停用自動隱藏" + +-#~ msgid "Icon size" +-#~ msgstr "圖示大小" +- + #~ msgid "Position of the dock" + #~ msgstr "Dock 的位置" + +-- +2.38.1 + + +From dc47faaf827011e5dd7a53f9007ea618c6e88203 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 8 Oct 2021 19:36:18 +0200 +Subject: [PATCH 09/11] Add dash-to-panel + +--- + extensions/dash-to-panel/COPYING | 341 + + extensions/dash-to-panel/README.md | 195 + + extensions/dash-to-panel/Settings.ui | 8166 +++++++++++++++++ + extensions/dash-to-panel/appIcons.js | 1964 ++++ + extensions/dash-to-panel/convenience.js | 89 + + extensions/dash-to-panel/extension.js | 144 + + .../img/highlight_stacked_bg.svg | 7 + + .../img/highlight_stacked_bg_2.svg | 7 + + .../img/highlight_stacked_bg_3.svg | 7 + + extensions/dash-to-panel/intellihide.js | 401 + + extensions/dash-to-panel/meson.build | 34 + + extensions/dash-to-panel/metadata.json.in | 12 + + ...shell.extensions.dash-to-panel.gschema.xml | 1278 +++ + extensions/dash-to-panel/overview.js | 536 ++ + extensions/dash-to-panel/panel.js | 1563 ++++ + extensions/dash-to-panel/panelManager.js | 901 ++ + extensions/dash-to-panel/panelPositions.js | 61 + + extensions/dash-to-panel/panelSettings.js | 112 + + extensions/dash-to-panel/panelStyle.js | 326 + + extensions/dash-to-panel/prefs.js | 2433 +++++ + extensions/dash-to-panel/progress.js | 598 ++ + extensions/dash-to-panel/proximity.js | 262 + + extensions/dash-to-panel/stylesheet.css | 151 + + extensions/dash-to-panel/taskbar.js | 1602 ++++ + extensions/dash-to-panel/transparency.js | 269 + + extensions/dash-to-panel/utils.js | 1035 +++ + extensions/dash-to-panel/windowPreview.js | 1145 +++ + meson.build | 1 + + po/cs.po | 1282 ++- + po/de.po | 1268 ++- + po/es.po | 1345 ++- + po/fr.po | 1390 +++ + po/gl.po | 1309 ++- + po/hu.po | 1274 ++- + po/it.po | 1399 +++ + po/ja.po | 1448 ++- + po/kk.po | 572 ++ + po/pl.po | 1291 ++- + po/pt_BR.po | 441 +- + po/ru.po | 1391 ++- + po/sv.po | 1269 ++- + po/tr.po | 1289 ++- + po/uk.po | 440 +- + po/zh_CN.po | 1308 ++- + po/zh_TW.po | 1056 ++- + 45 files changed, 43357 insertions(+), 55 deletions(-) + create mode 100644 extensions/dash-to-panel/COPYING + create mode 100644 extensions/dash-to-panel/README.md + create mode 100644 extensions/dash-to-panel/Settings.ui + create mode 100644 extensions/dash-to-panel/appIcons.js + create mode 100644 extensions/dash-to-panel/convenience.js + create mode 100644 extensions/dash-to-panel/extension.js + create mode 100644 extensions/dash-to-panel/img/highlight_stacked_bg.svg + create mode 100644 extensions/dash-to-panel/img/highlight_stacked_bg_2.svg + create mode 100644 extensions/dash-to-panel/img/highlight_stacked_bg_3.svg + create mode 100644 extensions/dash-to-panel/intellihide.js + create mode 100644 extensions/dash-to-panel/meson.build + create mode 100644 extensions/dash-to-panel/metadata.json.in + create mode 100644 extensions/dash-to-panel/org.gnome.shell.extensions.dash-to-panel.gschema.xml + create mode 100644 extensions/dash-to-panel/overview.js + create mode 100644 extensions/dash-to-panel/panel.js + create mode 100755 extensions/dash-to-panel/panelManager.js + create mode 100644 extensions/dash-to-panel/panelPositions.js + create mode 100644 extensions/dash-to-panel/panelSettings.js + create mode 100644 extensions/dash-to-panel/panelStyle.js + create mode 100644 extensions/dash-to-panel/prefs.js + create mode 100644 extensions/dash-to-panel/progress.js + create mode 100644 extensions/dash-to-panel/proximity.js + create mode 100644 extensions/dash-to-panel/stylesheet.css + create mode 100644 extensions/dash-to-panel/taskbar.js + create mode 100644 extensions/dash-to-panel/transparency.js + create mode 100644 extensions/dash-to-panel/utils.js + create mode 100644 extensions/dash-to-panel/windowPreview.js + +diff --git a/extensions/dash-to-panel/COPYING b/extensions/dash-to-panel/COPYING +new file mode 100644 +index 00000000..8d61b15e +--- /dev/null ++++ b/extensions/dash-to-panel/COPYING +@@ -0,0 +1,341 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 Free Software Foundation, Inc. ++ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Library General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, not ++price. Our General Public Licenses are designed to make sure that you ++have the freedom to distribute copies of free software (and charge for ++this service if you wish), that you receive source code or can get it ++if you want it, that you can change the software or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++source code as you receive it, in any medium, provided that you ++conspicuously and appropriately publish on each copy an appropriate ++copyright notice and disclaimer of warranty; keep intact all the ++notices that refer to this License and to the absence of any warranty; ++and give any other recipients of the Program a copy of this License ++along with the Program. ++ ++You may charge a fee for the physical act of transferring a copy, and ++you may at your option offer warranty protection in exchange for a fee. ++ ++ 2. You may modify your copy or copies of the Program or any portion ++of it, thus forming a work based on the Program, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Program, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) Accompany it with the complete corresponding machine-readable ++ source code, which must be distributed under the terms of Sections ++ 1 and 2 above on a medium customarily used for software interchange; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, complete source ++code means all the source code for all modules it contains, plus any ++associated interface definition files, plus the scripts used to ++control compilation and installation of the executable. However, as a ++special exception, the source code distributed need not include ++anything that is normally distributed (in either source or binary ++form) with the major components (compiler, kernel, and so on) of the ++operating system on which the executable runs, unless that component ++itself accompanies the executable. ++ ++If distribution of executable or object code is made by offering ++access to copy from a designated place, then offering equivalent ++access to copy the source code from the same place counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program is ++void, and will automatically terminate your rights under this License. ++However, parties who have received copies, or rights, from you under ++this License will not have their licenses terminated so long as such ++parties remain in full compliance. ++ ++ 5. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program subject to ++these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties to ++this License. ++ ++ 7. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Program. ++ ++If any portion of this section is held invalid or unenforceable under ++any particular circumstance, the balance of the section is intended to ++apply and the section as a whole is intended to apply in other ++circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system, which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program under this License ++may add an explicit geographical distribution limitation excluding ++those countries, so that distribution is permitted only in or among ++countries not thus excluded. In such case, this License incorporates ++the limitation as if written in the body of this License. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the General Public License from time to time. Such new versions will ++be similar in spirit to the present version, but may differ in detail to ++address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Program ++specifies a version number of this License which applies to it and "any ++later version", you have the option of following the terms and conditions ++either of that version or of any later version published by the Free ++Software Foundation. If the Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, write to the author ++to ask for permission. For software which is copyrighted by the Free ++Software Foundation, write to the Free Software Foundation; we sometimes ++make exceptions for this. Our decision will be guided by the two goals ++of preserving the free status of all derivatives of our free software and ++of promoting the sharing and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ++OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ++TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING ++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR ++REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, ++INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING ++OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED ++TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY ++YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. It is safest ++to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least ++the "copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) year name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ , 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Library General ++Public License instead of this License. ++ +diff --git a/extensions/dash-to-panel/README.md b/extensions/dash-to-panel/README.md +new file mode 100644 +index 00000000..7b600b53 +--- /dev/null ++++ b/extensions/dash-to-panel/README.md +@@ -0,0 +1,195 @@ ++

++ ++

++

++ ++ ++ ++ ++

++ ++![](media/design/png/dtp-main-p2.png) ++ ++### Introduction ++ ++Dash to Panel is an icon taskbar for Gnome Shell. This extension moves the dash into the gnome main panel so that the application launchers and system tray are combined into a single panel, similar to that found in KDE Plasma and Windows 7+. A separate dock is no longer needed for easy access to running and favorited applications. ++ ++Beyond that, just about every aspect of the panel is fully customizable. From positioning and scaling panel elements to running indicators to multi-monitor display, to window previews and even intellihide, Dash to Panel has everything you need to make your workspace feel like home. ++ ++### Features ++ ++|Customizable appearance| ++|:-----:| ++|![screenshot](media/design/gif/customizable.gif)| ++|Hide & show panel elements and set their positions, sizes & colors| ++ ++## ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
Customizable running indicators
MetroCiliora/Dashes
CilioraSquares/Segmented
DashesDots/Solid
Set position, style, weight & color of running indicators to easily and quickly identify focused and unfocused applications
++ ++## ++ ++|Live Previews on Hover| ++|:-----:| ++|![screenshot](media/design/gif/previews.gif)| ++|Hover over the launcher icon for an open application to get a live window preview| ++ ++## ++|Launch by Number| ++|:-----:| ++|![](media/design/png/indicators-num.png.png)| ++|Optionally launch your favorite applications via keyboard| ++ ++## ++ ++|Panel Intellihide| ++|:-----:| ++|![Intellihide](media/design/gif/Intellihide.gif)| ++|Hide and reveal the panel according to your set preferences| ++ ++## ++|Additional Features|Feature Implemented| ++|:-----|:-----:| ++|Add "Show Desktop" button to panel|![](media/design/png/done.png)| ++|Isolate running apps by workspaces and/or monitors|![](media/design/png/done.png)| ++|Custom click behaviors (launch new window, cycle open windows, minimize, etc)|![](media/design/png/done.png)| ++|Integrate native Gnome appMenu into right-click secondary menu|![](media/design/png/done.png)| ++|Multi-monitor support|![](media/design/png/done.png)| ++|Dynamic transparency|![](media/design/png/done.png)| ++|Ungroup application windows|![](media/design/png/done.png)| ++|Export and import settings|![](media/design/png/done.png)| ++## ++ ++### Installation ++ ++**To install the most recent official release: ++[Visit Dash-to-Panel at GNOME Extensions](https://extensions.gnome.org/extension/1160/dash-to-panel/)** ++ ++To install a development version from source, please see the [Installation wiki page](https://github.com/jderose9/dash-to-panel/wiki/Installation). ++ ++## ++### FAQ ++ ++How do I customize the panel? [See the Wiki](https://github.com/home-sweet-gnome/dash-to-panel/wiki/Enable-and-Customize#customize-it) ++ ++How do I embed my bottom left notification drawer into the panel like a system tray? [Top Icons Plus](https://extensions.gnome.org/extension/2311/topicons-plus) or [(K)StatusNotifierItem/AppIndicator Support](https://extensions.gnome.org/extension/615/appindicator-support) ++ ++How do I add a traditional start menu? [Arc Menu](https://extensions.gnome.org/extension/3628/arcmenu/) ++ ++How do I disable the hot corner? [No Topleft Hot Corner](https://extensions.gnome.org/extension/118/no-topleft-hot-corner) ++ ++How do I move the notifications to somewhere other than the top center? [Panel OSD](https://extensions.gnome.org/extension/708/panel-osd) ++ ++How do I display Minimize & Maximize buttons? In the Tweak Tool application, turn on `Windows > Titlebar Buttons > Minimize & Maximize`. ++ ++How do I reset the extension to its default settings? `dconf reset -f /org/gnome/shell/extensions/dash-to-panel/`. ++ ++## ++### Themes ++While this extension works well with most popular Gnome Shell themes, the following themes are known to have explicitly added custom styles for this extension: ++- [Ciliora Tertia](https://github.com/zagortenay333/ciliora-tertia-shell) / [Ciliora Secunda](https://github.com/zagortenay333/ciliora-secunda-shell) ++- [Plano](https://github.com/lassekongo83/plano-theme) ++ ++ ++## ++### Compatibility ++ ++This extension has been tested with Gnome 3.18+. ++ ++This extension manipulates the Gnome Main Panel, aka Top Bar. So, most other extensions which operate on the top bar should be compatible. ++ ++## ++### Donation ++ ++Dash-to-Panel is provided free of charge. If it has improved your workflow, or you had a great support experience, feel free to say thanks by making a donation to the developers. (If you would like your donation to go to a specific developer, you may mention it in the note field during payment) ++ ++[![Donate via Paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Y5PBB2CRJ6F2W&source=url) ++ ++## ++### Volunteers needed! ++ ++This extension could be even better with your help! Any items in the issue tracker labelled `help wanted` or `good first issue` are up for grabs. For more info, see the [Contributing wiki page](https://github.com/jderose9/dash-to-panel/wiki/Contributing). ++ ++## ++### Credits ++ ++This extension is developed and maintained by [@jderose9](https://github.com/jderose9) and [@charlesg99](https://github.com/charlesg99). ++ ++Significant portions of code in this extension were derived from [Dash-to-Dock](https://micheleg.github.io/dash-to-dock/index.html). ++ ++Additional credits: This extension leverages the work for [ZorinOS Taskbar](https://github.com/ZorinOS/zorin-taskbar) (used in [ZorinOS](https://zorinos.com/)) to show window previews and allow the dash from [Dash-to-Dock](https://micheleg.github.io/dash-to-dock/index.html) to be embedded in the Gnome main panel. ++Code to set anchor position taken from [Thoma5/gnome-shell-extension-bottompanel](https://github.com/Thoma5/gnome-shell-extension-bottompanel). ++Pattern for moving panel contents based on [Frippery Move Clock](http://frippery.org/extensions/) by R M Yorston. ++Ideas for recursing child actors and assigning inline styles are based on code from the extension [StatusAreaHorizontalSpacing](https://bitbucket.org/mathematicalcoffee/status-area-horizontal-spacing-gnome-shell-extension). ++## ++ ++#### Thanks to the following people for contributing via pull requests: ++ ++- @franglais125 for launching apps by number (w/ overlay), bug fixes, and issue support ++- @LinxGem33 and @sbarrett322 for artwork, logos, screenshots and design effort ++- @dziku1337 for peek mode in window previews ++- @robrobinbin for configuring appMenu on/off in the panel ++- @MartinPL for toggling favorites on/off in panel ++- @jackwickham for thumbnail middle and right click actions ++- @abakkk for centering the taskbar icons in the panel, and animated taskbar hovering ++- @quasoft for changing of font weight of ungrouped application titles ++- @jordanribera for using icon's dominant color as running indicator color ++- @tper0700 for dynamically building context menu based on system capabilities ++- @levacic for configurable minimized application title font color ++- @l3nn4rt for toggling workspace switch popup ++- @hlechner for adjustable show desktop line color and window preview icon size ++- @ArtyomZorin for animated urgent icons ++- @jvpessoa10 for additional click window cycle options ++- @marksvc for assigning percent of display for panel length ++ ++#### Bug Fixes: ++@imrvelj, @Teslator, @bil-elmoussaoui, @brandon-schumann, @sw9, @rockon999 , @lexruee, @3v1n0, @freeroot, @moqmar, @ArtyomZorin, @lkc0987, @saibotk, @vanillajonathan, @Zkdc, @leebickmtu, @l3nn4rt, @Melix19, @Aikatsui, @melix99 ++ ++#### Documentation Improvements: ++@BoQsc, @zakkak, @dandv ++ ++#### Translations: ++@frnogueira (pt_BR), @zeten30 (cs), @franglais125 / @calotam / @oeramirez (es), @LaurentTreguier / @SolarLiner (fr), @elsieholmes (uk), @hosiet (zh\_CN), @jonnius / @linuxr01 (de), @urbalazs / @pappfer (hu), @crayxt (kk), @pkomur / @MartinPL / @alex4401 (pl), @AlexGluck / @GoodNike / @rjapolov / @vantu5z (ru), @sicklylife-jp / @ryonakano (ja), @oltulu / @TeknoMobil / @daenney (tr), @sbadux / @kowalski7cc / @l3nn4rt (it), @OriginCode / @pan93412 (zh\_TW), @ojn (sv), @frandieguez (gl) ++ ++ ++## ++### License & Terms ![](media/design/png/copyleft-16.png) ++ ++Dash to Panel is available under the terms of the GPL-v2 or later license See [`COPYING`](https://github.com/jderose9/dash-to-panel/blob/master/COPYING) for details. ++ ++![](https://img.shields.io/badge/Language-JavaScript-yellow.svg) ![](https://img.shields.io/badge/Licence-GPL--2.0-blue.svg) +diff --git a/extensions/dash-to-panel/Settings.ui b/extensions/dash-to-panel/Settings.ui +new file mode 100644 +index 00000000..9589a207 +--- /dev/null ++++ b/extensions/dash-to-panel/Settings.ui +@@ -0,0 +1,8166 @@ ++ ++ ++ ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ False ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Animation type ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Simple ++ Ripple ++ Plank ++ ++ ++ ++ False ++ False ++ end ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ False ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 24 ++ 32 ++ ++ ++ True ++ False ++ 12 ++ Duration ++ True ++ 0 ++ end ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ True ++ animate_appicon_hover_options_duration_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Rotation ++ 0 ++ end ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ True ++ animate_appicon_hover_options_rotation_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ Travel ++ 0 ++ end ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ True ++ animate_appicon_hover_options_travel_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ Zoom ++ 0 ++ end ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ True ++ end ++ True ++ animate_appicon_hover_options_zoom_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ Convexity ++ 0 ++ end ++ ++ ++ 0 ++ 4 ++ ++ ++ ++ ++ True ++ True ++ end ++ True ++ animate_appicon_hover_options_convexity_adjustment ++ 1 ++ 1 ++ right ++ ++ ++ ++ 1 ++ 4 ++ ++ ++ ++ ++ True ++ False ++ Extent ++ 0 ++ end ++ ++ ++ 0 ++ 5 ++ ++ ++ ++ ++ True ++ True ++ end ++ True ++ animate_appicon_hover_options_extent_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ 1 ++ 5 ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 100 ++ 1 ++ 10 ++ ++ ++ 0 ++ 300 ++ 1 ++ 5 ++ ++ ++ -30 ++ 30 ++ 1 ++ 5 ++ ++ ++ 0 ++ 100 ++ 1 ++ 5 ++ ++ ++ 100 ++ 250 ++ 1 ++ 5 ++ ++ ++ 0 ++ 3 ++ 0.1 ++ 1 ++ ++ ++ 1 ++ 10 ++ 0.1 ++ 1 ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ True ++ Nothing yet! ++ True ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ When set to minimize, double clicking minimizes all the windows of the application. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shift+Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise windows ++ Minimize window ++ Launch new instance ++ Cycle through windows ++ Cycle windows + minimize ++ Toggle single / Preview multiple ++ Toggle single / Cycle multiple ++ Quit ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behavior for Middle-Click. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Middle-Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise windows ++ Minimize window ++ Launch new instance ++ Cycle through windows ++ Cycle windows + minimize ++ Toggle single / Preview multiple ++ Quit ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behavior for Shift+Middle-Click. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shift+Middle-Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Raise windows ++ Minimize window ++ Launch new instance ++ Cycle through windows ++ Cycle windows + minimize ++ Toggle single / Preview multiple ++ Quit ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ center ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Integrate <i>AppMenu</i> items ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ center ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ <i>Show Details</i> menu item ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 10 ++ 1 ++ 5 ++ ++ ++ 5 ++ 1 ++ 5 ++ ++ ++ 50 ++ 9999 ++ 25 ++ 100 ++ ++ ++ 5 ++ 100 ++ 5 ++ 5 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Highlight focused application ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 8 ++ ++ ++ True ++ False ++ True ++ Icon dominant color ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Custom color ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Highlight opacity ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ 5 ++ focus_highlight_opacity_adjustment ++ 5 ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Indicator size (px) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 0 ++ dot_size_adjustment ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Indicator color - Icon Dominant ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ ++ ++ True ++ False ++ True ++ Indicator color - Override Theme ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 4 ++ 32 ++ ++ ++ True ++ False ++ True ++ 1 window open (or ungrouped) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ end ++ ++ ++ Apply to all ++ True ++ True ++ True ++ ++ ++ False ++ True ++ 4 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ 2 windows open ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ 3 windows open ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ 4+ windows open ++ 0 ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 12 ++ ++ ++ True ++ False ++ True ++ Use different for unfocused ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 4 ++ 32 ++ ++ ++ True ++ False ++ True ++ 1 window open (or ungrouped) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ end ++ ++ ++ Apply to all ++ True ++ True ++ True ++ ++ ++ False ++ True ++ 4 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ 2 windows open ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ 3 windows open ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ 4+ windows open ++ 0 ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 4 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 6 ++ 24 ++ 1 ++ 100 ++ ++ ++ 1000 ++ 10 ++ 100 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ group_apps_label_font_size_adjustment ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Font size (px) of the application titles (default is 14) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Font weight of application titles ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ inherit from theme ++ normal ++ lighter ++ bold ++ bolder ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Font color of the application titles ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Font color of the minimized application titles ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Maximum width (px) of the application titles (default is 160) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ group_apps_label_max_width_adjustment ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Use a fixed width for the application titles ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ The application titles all have the same width, even if their texts are shorter than the maximum width. The maximum width value is used as the fixed width. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Display running indicators on unfocused applications ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Use the favorite icons as application launchers ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 10 ++ 2000 ++ 10 ++ 100 ++ ++ ++ 10 ++ 4000 ++ 10 ++ 100 ++ ++ ++ 10000 ++ 10 ++ 100 ++ ++ ++ 1 ++ 9990 ++ 10 ++ 100 ++ ++ ++ 1 ++ 5000 ++ 10 ++ 100 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ True ++ ++ ++ True ++ False ++ True ++ Only hide the panel when it is obstructed by windows ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 4 ++ ++ ++ True ++ False ++ True ++ The panel hides from ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ All windows ++ Focused windows ++ Maximized windows ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Require pressure at the edge of the screen to reveal the panel ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 4 ++ ++ ++ True ++ False ++ True ++ Required pressure threshold (px) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ intellihide_pressure_threshold_adjustment ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Required pressure timeout (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ intellihide_pressure_time_adjustment ++ True ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Allow the panel to be revealed while in fullscreen mode ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Only hide secondary panels (requires multi-monitors option) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ center ++ 12 ++ e.g. <Super>i ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Keyboard shortcut to reveal and hold the panel ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Syntax: <Shift>, <Ctrl>, <Alt>, <Super> ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Hide and reveal animation duration (ms) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ intellihide_animation_time_adjustment ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Delay before hiding the panel (ms) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 10 ++ intellihide_close_delay_adjustment ++ True ++ 10 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Delay before enabling intellihide on start (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 10 ++ intellihide_enable_hide_delay_adjustment ++ True ++ 10 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 9999 ++ 25 ++ 100 ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ 255 ++ 10 ++ 25 ++ ++ ++ 1000 ++ 10 ++ 50 ++ ++ ++ 50 ++ 500 ++ 10 ++ 50 ++ ++ ++ 100 ++ 5 ++ 10 ++ ++ ++ 50 ++ 1 ++ 5 ++ ++ ++ 100 ++ 800 ++ 10 ++ 50 ++ ++ ++ 9999 ++ 25 ++ 100 ++ ++ ++ 6 ++ 24 ++ 1 ++ 100 ++ ++ ++ 8 ++ 48 ++ 1 ++ 100 ++ ++ ++ True ++ True ++ in ++ 460 ++ 480 ++ ++ ++ True ++ False ++ True ++ True ++ natural ++ natural ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ preview_timeout_adjustment ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Time (ms) before showing (400 is default) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Animation time (ms) ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ preview_animation_time_adjustment ++ True ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ True ++ Time (ms) before hiding (100 is default) ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ False ++ 12 ++ 4 ++ True ++ ++ ++ 4 ++ True ++ False ++ start ++ 4 ++ Immediate on application icon click ++ True ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ 4 ++ 25 ++ leave_timeout_adjustment ++ True ++ 25 ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Middle click on the preview to close the window ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Window previews preferred size (px) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 100 ++ preview_size_adjustment ++ True ++ 100 ++ ++ ++ 2 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Window previews aspect ratio Y (height) ++ True ++ 0 ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Window previews padding (px) ++ True ++ 0 ++ ++ ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 50 ++ preview_padding_adjustment ++ True ++ 50 ++ ++ ++ 2 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ end ++ 2 ++ True ++ ++ ++ True ++ False ++ end ++ center ++ ++ 1 ++ 2 ++ 3 ++ 4 ++ 5 ++ 6 ++ 7 ++ 8 ++ 9 ++ 10 ++ 11 ++ 12 ++ 13 ++ 14 ++ 15 ++ 16 ++ 17 ++ 18 ++ 19 ++ 20 ++ 21 ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Fixed ++ True ++ True ++ True ++ end ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ 2 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Window previews aspect ratio X (width) ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ end ++ 2 ++ True ++ ++ ++ True ++ False ++ end ++ center ++ ++ 1 ++ 2 ++ 3 ++ 4 ++ 5 ++ 6 ++ 7 ++ 8 ++ 9 ++ 10 ++ 11 ++ 12 ++ 13 ++ 14 ++ 15 ++ 16 ++ 17 ++ 18 ++ 19 ++ 20 ++ 21 ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ Fixed ++ True ++ True ++ True ++ end ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 2 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Use custom opacity for the previews background ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ If disabled, the previews background have the same opacity as the panel ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 8 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ 5 ++ preview_opacity_adjustment ++ 5 ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Close button and header position ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ end ++ 32 ++ ++ ++ Bottom ++ True ++ True ++ False ++ center ++ center ++ True ++ True ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Top ++ True ++ True ++ False ++ center ++ center ++ bottom ++ True ++ preview_title_position_bottom_button ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Display window preview headers ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 32 ++ ++ ++ True ++ False ++ 8 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 6 ++ preview_custom_icon_size_adjustment ++ True ++ 6 ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Icon size (px) of the window preview ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ If disabled, the previews icon size will be based on headerbar size ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ 4 ++ 6 ++ preview_title_font_size_adjustment ++ True ++ 6 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Font size (px) of the preview titles ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Font weight of the preview titles ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ end ++ center ++ ++ inherit from theme ++ normal ++ lighter ++ bold ++ bolder ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Font color of the preview titles ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ 0 ++ 4 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ 6 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Enable window peeking ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ When hovering over a window preview for some time, the window gets distinguished. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Enter window peeking mode timeout (ms) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 50 ++ enter_peek_mode_timeout_adjustment ++ True ++ 50 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Time of inactivity while hovering over a window preview needed to enter the window peeking mode. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Window peeking mode opacity ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 0 ++ peek_mode_opacity_adjustment ++ True ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ All windows except for the peeked one have their opacity set to the same value. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ 0 ++ 3 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 2000 ++ 10 ++ 50 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ 4 ++ 50 ++ scroll_icon_options_delay_adjustment ++ True ++ 50 ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Delay between mouse scroll events (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Use this value to limit the number of captured mouse scroll events. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 2000 ++ 10 ++ 50 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ 4 ++ 50 ++ scroll_panel_options_delay_adjustment ++ True ++ 50 ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Delay between mouse scroll events (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Use this value to limit the number of captured mouse scroll events. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Show popup when changing workspace ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ This affects workspace popup when scrolling on the panel only. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 10000 ++ 250 ++ 1000 ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ vertical ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ center ++ ++ Super ++ Super + Alt ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Hotkeys prefix ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Hotkeys will either be Super+Number or Super+Alt+Num ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ 80 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ center ++ ++ Never ++ Show temporarily ++ Always visible ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Number overlay ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Temporarily show the application numbers over the icons when using the hotkeys. ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ True ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ shortcut_time_adjustment ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Hide timeout (ms) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ center ++ 12 ++ e.g. <Super>q ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Shortcut to show the overlay for 2 seconds ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Syntax: <Shift>, <Ctrl>, <Alt>, <Super> ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Show window previews on hotkey ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show previews when the application have multiple instances ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ end ++ center ++ ++ Number row ++ Numeric keypad ++ Both ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Hotkeys are activated with ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Select which keyboard number keys are used to activate the hotkeys ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 100 ++ 1 ++ 10 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Current Show Applications icon ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ 32 ++ 32 ++ True ++ False ++ end ++ gtk-missing-image ++ 32 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ 140 ++ True ++ False ++ False ++ Select a Show Applications image icon ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Custom Show Applications image icon ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ True ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ 0 ++ show_applications_side_padding_adjustment ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show Applications icon side padding (px) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Override escape key and return to desktop ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Animate <i>Show Applications</i>. ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ 5000 ++ 10 ++ 100 ++ ++ ++ 5000 ++ 10 ++ 100 ++ ++ ++ 1 ++ 40 ++ 1 ++ 10 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 4 ++ 32 ++ ++ ++ True ++ False ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 1 ++ show_showdesktop_width_adjustment ++ True ++ 1 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Override Show Desktop line color ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ end ++ ++ ++ True ++ True ++ True ++ end ++ True ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Reveal the desktop when hovering the Show Desktop button ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 4 ++ ++ ++ True ++ False ++ True ++ Delay before revealing the desktop (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 1 ++ show_showdesktop_delay_adjustment ++ True ++ 1 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Fade duration (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ 4 ++ 1 ++ show_showdesktop_time_adjustment ++ True ++ 1 ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ 2000 ++ 1 ++ 10 ++ ++ ++ 200 ++ 1 ++ 10 ++ ++ ++ 100 ++ 5 ++ 10 ++ ++ ++ 100 ++ 5 ++ 10 ++ ++ ++ 100 ++ 5 ++ 10 ++ ++ ++ 100 ++ 5 ++ 10 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 4 ++ ++ ++ True ++ False ++ True ++ The panel background opacity is affected by ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ All windows ++ Focused windows ++ Maximized windows ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ 4 ++ 50 ++ trans_distance_adjustment ++ True ++ 50 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Change opacity when a window gets closer than (px) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ ++ ++ True ++ False ++ 12 ++ Change opacity to (%) ++ True ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ 0 ++ trans_opacity_min_adjustment ++ ++ ++ False ++ False ++ end ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ 4 ++ 50 ++ trans_anim_time_adjustment ++ True ++ 50 ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Opacity change animation duration (ms) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ 0.33 ++ 1 ++ 0.01 ++ 0.1 ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ 32 ++ ++ ++ True ++ False ++ True ++ Display the main panel on ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ False ++ True ++ Display panels on all monitors ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Panel Intellihide ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Hide and reveal the panel according to preferences ++ True ++ 40 ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ ++ ++ True ++ False ++ True ++ Order and positions on monitor ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ Apply changes to all monitors ++ True ++ True ++ False ++ 12 ++ 4 ++ 4 ++ True ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ 0 ++ none ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 6 ++ 6 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ baseline ++ True ++ panel_size_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ Panel thickness ++(default is 48) ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ Panel length (%) ++(default is 100) ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ panel_length_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Start ++ Middle ++ End ++ ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ Anchor ++ 0 ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ True ++ Panel screen position ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 32 ++ ++ ++ Bottom ++ True ++ True ++ False ++ center ++ center ++ 0 ++ True ++ True ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ Top ++ True ++ True ++ False ++ center ++ center ++ 0 ++ bottom ++ True ++ position_bottom_button ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Left ++ True ++ True ++ False ++ center ++ center ++ 0 ++ bottom ++ True ++ position_bottom_button ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ Right ++ True ++ True ++ False ++ center ++ center ++ 0 ++ bottom ++ True ++ position_bottom_button ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 0 ++ 2 ++ 2 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ none ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ ++ ++ True ++ False ++ Position ++ ++ ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 6 ++ 6 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ App Icon Margin ++(default is 8) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ appicon_margin_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 6 ++ 6 ++ 32 ++ ++ ++ True ++ False ++ App Icon Padding ++(default is 4) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ appicon_padding_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Running indicator position ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 32 ++ ++ ++ Bottom ++ True ++ True ++ False ++ center ++ True ++ True ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ Top ++ True ++ True ++ False ++ center ++ bottom ++ True ++ dots_bottom_button ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ Left ++ True ++ True ++ False ++ center ++ True ++ dots_bottom_button ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ Right ++ True ++ True ++ False ++ center ++ True ++ dots_bottom_button ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Running indicator style (Focused app) ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ end ++ center ++ ++ Dots ++ Squares ++ Dashes ++ Segmented ++ Solid ++ Ciliora ++ Metro ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Running indicator style (Unfocused apps) ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ end ++ center ++ ++ Dots ++ Squares ++ Dashes ++ Segmented ++ Solid ++ Ciliora ++ Metro ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Override panel theme background color ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ end ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Override panel theme background opacity ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 6 ++ ++ ++ True ++ False ++ True ++ Panel background opacity (%) ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ 0 ++ trans_opacity_adjustment ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ vertical ++ ++ ++ True ++ False ++ True ++ Dynamic background opacity ++ True ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Change opacity when a window gets close to the panel ++ True ++ 40 ++ 0 ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ end ++ center ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Override panel theme gradient ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 6 ++ ++ ++ True ++ False ++ True ++ Gradient top color and opacity (%) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Gradient bottom color and opacity (%) ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ 0 ++ trans_gradient_opacity1_adjustment ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ 0 ++ trans_gradient_opacity2_adjustment ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Animate hovering app icons ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 1 ++ ++ ++ ++ ++ True ++ False ++ Style ++ ++ ++ 1 ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show favorite applications ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show running applications ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show favorite applications on secondary panels ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show <i>AppMenu</i> button ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Top Bar > Show App Menu must be enabled in Tweak Tool ++ True ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 4 ++ 32 ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show window previews on hover ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Show tooltip on hover ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Isolate Workspaces ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Isolate monitors ++ True ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Click empty space to close overview ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Ungroup applications ++ True ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ 2 ++ ++ ++ ++ ++ True ++ False ++ Behavior ++ ++ ++ 2 ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Behaviour when clicking on the icon of a running application. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Click action ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ Cycle windows + minimize ++ Cycle through windows ++ Toggle single / Preview multiple ++ Toggle single / Cycle multiple ++ Toggle windows ++ Raise windows ++ Launch new instance ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 16 ++ 6 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ True ++ Scroll panel action ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Behavior when mouse scrolling over the panel. ++ True ++ 0 ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ True ++ Scroll icon action ++ 0 ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Behavior when mouse scrolling over an application icon. ++ True ++ 0 ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ True ++ ++ Do nothing ++ Switch workspace ++ Cycle windows ++ Change volume ++ ++ ++ ++ 2 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ True ++ ++ Do nothing ++ Cycle windows ++ Same as panel ++ ++ ++ ++ 2 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ True ++ end ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ True ++ Enable Super+(0-9) as shortcuts to activate apps. It can also be used together with Shift and Ctrl. ++ True ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Use hotkeys to activate apps ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ True ++ True ++ center ++ center ++ 0.46000000834465027 ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ 1 ++ 0 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ 3 ++ ++ ++ ++ ++ True ++ False ++ Action ++ ++ ++ 3 ++ False ++ ++ ++ ++ ++ True ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ vertical ++ 24 ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ True ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 6 ++ 6 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Tray Font Size ++(0 = theme default) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ tray_size_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ LeftBox Font Size ++(0 = theme default) ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ leftbox_size_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 12 ++ 32 ++ ++ ++ True ++ False ++ Tray Item Padding ++(-1 = theme default) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ tray_padding_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ Status Icon Padding ++(-1 = theme default) ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ statusicon_padding_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ LeftBox Padding ++(-1 = theme default) ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ baseline ++ True ++ leftbox_padding_adjustment ++ 0 ++ 0 ++ right ++ ++ ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ False ++ True ++ Animate switching applications ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ True ++ False ++ True ++ Animate launching new windows ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ False ++ True ++ Keep original gnome-shell dash (overview) ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ True ++ False ++ True ++ Force Activities hot corner on primary monitor ++ 0 ++ ++ ++ 0 ++ 3 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 3 ++ ++ ++ ++ ++ True ++ False ++ True ++ Activate panel menu buttons (e.g. date menu) on click only ++ 0 ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ True ++ Keep original gnome-shell top panel ++ 0 ++ ++ ++ 0 ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ center ++ ++ ++ 1 ++ 1 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 3 ++ ++ ++ ++ ++ True ++ False ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ 100 ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 20 ++ 32 ++ ++ ++ True ++ False ++ True ++ App icon secondary (right-click) menu ++ 0 ++ ++ ++ 0 ++ 0 ++ ++ ++ ++ ++ True ++ True ++ True ++ center ++ ++ ++ True ++ False ++ emblem-system-symbolic ++ ++ ++ ++ ++ ++ 1 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 4 ++ ++ ++ ++ ++ Advanced Options ++ True ++ True ++ True ++ start ++ ++ ++ False ++ True ++ 5 ++ ++ ++ ++ ++ 4 ++ ++ ++ ++ ++ True ++ False ++ center ++ Fine-Tune ++ ++ ++ 4 ++ False ++ ++ ++ ++ ++ False ++ 24 ++ 24 ++ 24 ++ 24 ++ True ++ True ++ vertical ++ 5 ++ ++ ++ True ++ False ++ vertical ++ ++ ++ True ++ False ++ <b>Dash-to-Panel</b> ++ True ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ center ++ ++ ++ True ++ False ++ end ++ version: ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ False ++ start ++ ... ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ GitHub ++ True ++ True ++ True ++ ++ center ++ none ++ https://github.com/jderose9/dash-to-panel ++ ++ ++ False ++ True ++ 2 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ False ++ 20 ++ 0 ++ in ++ ++ ++ True ++ False ++ none ++ ++ ++ True ++ True ++ ++ ++ True ++ False ++ 12 ++ 12 ++ 12 ++ 12 ++ 6 ++ 32 ++ ++ ++ True ++ False ++ 12 ++ True ++ Use the buttons below to create a settings file from your current preferences that can be imported on a different machine. ++ True ++ 0 ++ ++ ++ ++ 0 ++ 1 ++ 2 ++ ++ ++ ++ ++ True ++ False ++ start ++ Export and import settings ++ ++ ++ 0 ++ 0 ++ 2 ++ ++ ++ ++ ++ Export to file ++ True ++ True ++ True ++ ++ ++ 0 ++ 2 ++ ++ ++ ++ ++ Import from file ++ True ++ True ++ True ++ ++ ++ 1 ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ True ++ True ++ end ++ <span size="small">This program comes with ABSOLUTELY NO WARRANTY. ++See the <a href="https://www.gnu.org/licenses/old-licenses/gpl-2.0.html">GNU General Public License, version 2 or later</a> for details.</span> ++ True ++ center ++ True ++ ++ ++ True ++ True ++ 6 ++ ++ ++ ++ ++ 5 ++ ++ ++ ++ ++ True ++ False ++ About ++ ++ ++ 5 ++ False ++ ++ ++ ++ +diff --git a/extensions/dash-to-panel/appIcons.js b/extensions/dash-to-panel/appIcons.js +new file mode 100644 +index 00000000..5cfb1350 +--- /dev/null ++++ b/extensions/dash-to-panel/appIcons.js +@@ -0,0 +1,1964 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++ ++const Clutter = imports.gi.Clutter; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Gtk = imports.gi.Gtk; ++const Signals = imports.signals; ++const Lang = imports.lang; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++ ++const Config = imports.misc.config; ++const AppDisplay = imports.ui.appDisplay; ++const AppFavorites = imports.ui.appFavorites; ++const Dash = imports.ui.dash; ++const DND = imports.ui.dnd; ++const IconGrid = imports.ui.iconGrid; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const Util = imports.misc.util; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++const Panel = Me.imports.panel; ++const PanelSettings = Me.imports.panelSettings; ++const Taskbar = Me.imports.taskbar; ++const Progress = Me.imports.progress; ++const _ = imports.gettext.domain(Utils.TRANSLATION_DOMAIN).gettext; ++ ++//timeout names ++const T1 = 'setStyleTimeout'; ++const T2 = 'mouseScrollTimeout'; ++const T3 = 'showDotsTimeout'; ++const T4 = 'overviewWindowDragEndTimeout'; ++const T5 = 'switchWorkspaceTimeout'; ++const T6 = 'displayProperIndicatorTimeout'; ++ ++//right padding defined for .overview-label in stylesheet.css ++const TITLE_RIGHT_PADDING = 8; ++ ++let LABEL_GAP = 5; ++let MAX_INDICATORS = 4; ++var DEFAULT_PADDING_SIZE = 4; ++ ++let DOT_STYLE = { ++ DOTS: "DOTS", ++ SQUARES: "SQUARES", ++ DASHES: "DASHES", ++ SEGMENTED: "SEGMENTED", ++ CILIORA: "CILIORA", ++ METRO: "METRO", ++ SOLID: "SOLID" ++} ++ ++let DOT_POSITION = { ++ TOP: "TOP", ++ BOTTOM: "BOTTOM", ++ LEFT: 'LEFT', ++ RIGHT: 'RIGHT' ++} ++ ++let recentlyClickedAppLoopId = 0; ++let recentlyClickedApp = null; ++let recentlyClickedAppWindows = null; ++let recentlyClickedAppIndex = 0; ++let recentlyClickedAppMonitorIndex; ++ ++let tracker = Shell.WindowTracker.get_default(); ++let menuRedisplayFunc = !!AppDisplay.AppIconMenu.prototype._rebuildMenu ? '_rebuildMenu' : '_redisplay'; ++ ++/** ++ * Extend AppIcon ++ * ++ * - Apply a css class based on the number of windows of each application (#N); ++ * - Draw a dot for each window of the application based on the default "dot" style which is hidden (#N); ++ * a class of the form "running#N" is applied to the AppWellIcon actor. ++ * like the original .running one. ++ * - add a .focused style to the focused app ++ * - Customize click actions. ++ * - Update minimization animation target ++ * ++ */ ++ ++var taskbarAppIcon = Utils.defineClass({ ++ Name: 'DashToPanel.TaskbarAppIcon', ++ Extends: AppDisplay.AppIcon, ++ ParentConstrParams: [[0, 'app'], [2]], ++ ++ _init: function(appInfo, panel, iconParams, previewMenu, iconAnimator) { ++ this.dtpPanel = panel; ++ this._nWindows = 0; ++ this.window = appInfo.window; ++ this.isLauncher = appInfo.isLauncher; ++ this._previewMenu = previewMenu; ++ this.iconAnimator = iconAnimator; ++ ++ this._timeoutsHandler = new Utils.TimeoutsHandler(); ++ ++ // Fix touchscreen issues before the listener is added by the parent constructor. ++ this._onTouchEvent = function(actor, event) { ++ if (event.type() == Clutter.EventType.TOUCH_BEGIN) { ++ // Open the popup menu on long press. ++ this._setPopupTimeout(); ++ } else if (this._menuTimeoutId != 0 && (event.type() == Clutter.EventType.TOUCH_END || event.type() == Clutter.EventType.TOUCH_CANCEL)) { ++ // Activate/launch the application. ++ this.activate(1); ++ this._removeMenuTimeout(); ++ } ++ // Disable dragging via touch screen as it's buggy as hell. Not perfect for tablet users, but the alternative is way worse. ++ // Also, EVENT_PROPAGATE launches applications twice with this solution, so this.activate(1) above must only be called if there's already a window. ++ return Clutter.EVENT_STOP; ++ }; ++ // Hack for missing TOUCH_END event. ++ this._onLeaveEvent = function(actor, event) { ++ this.actor.fake_release(); ++ if (this._menuTimeoutId != 0) this.activate(1); // Activate/launch the application if TOUCH_END didn't fire. ++ this._removeMenuTimeout(); ++ }; ++ ++ this.callParent('_init', appInfo.app, iconParams); ++ ++ Utils.wrapActor(this.icon); ++ Utils.wrapActor(this); ++ ++ this._dot.set_width(0); ++ this._isGroupApps = Me.settings.get_boolean('group-apps'); ++ ++ this._container = new St.Widget({ style_class: 'dtp-container', layout_manager: new Clutter.BinLayout() }); ++ this._dotsContainer = new St.Widget({ layout_manager: new Clutter.BinLayout() }); ++ this._dtpIconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(), style: getIconContainerStyle(panel.checkIfVertical()) }); ++ ++ this.actor.remove_actor(this._iconContainer); ++ ++ this._dtpIconContainer.add_child(this._iconContainer); ++ ++ if (appInfo.window) { ++ let box = new St.BoxLayout(); ++ ++ this._windowTitle = new St.Label({ ++ y_align: Clutter.ActorAlign.CENTER, ++ x_align: Clutter.ActorAlign.START, ++ style_class: 'overview-label' ++ }); ++ ++ this._updateWindowTitle(); ++ this._updateWindowTitleStyle(); ++ ++ this._scaleFactorChangedId = Utils.getStageTheme().connect('changed', () => this._updateWindowTitleStyle()); ++ ++ box.add_child(this._dtpIconContainer); ++ box.add_child(this._windowTitle); ++ ++ this._dotsContainer.add_child(box); ++ } else { ++ this._dotsContainer.add_child(this._dtpIconContainer); ++ } ++ ++ this._container.add_child(this._dotsContainer); ++ this.actor.set_child(this._container); ++ ++ if (panel.checkIfVertical()) { ++ this.actor.set_width(panel.geom.w); ++ } ++ ++ // Monitor windows-changes instead of app state. ++ // Keep using the same Id and function callback (that is extended) ++ if(this._stateChangedId > 0) { ++ this.app.disconnect(this._stateChangedId); ++ this._stateChangedId = 0; ++ } ++ ++ this._onAnimateAppiconHoverChanged(); ++ this._setAppIconPadding(); ++ this._showDots(); ++ ++ this._focusWindowChangedId = global.display.connect('notify::focus-window', ++ Lang.bind(this, this._onFocusAppChanged)); ++ ++ this._windowEnteredMonitorId = this._windowLeftMonitorId = 0; ++ this._stateChangedId = this.app.connect('windows-changed', Lang.bind(this, this.onWindowsChanged)); ++ ++ if (!this.window) { ++ if (Me.settings.get_boolean('isolate-monitors')) { ++ this._windowEnteredMonitorId = Utils.DisplayWrapper.getScreen().connect('window-entered-monitor', this.onWindowEnteredOrLeft.bind(this)); ++ this._windowLeftMonitorId = Utils.DisplayWrapper.getScreen().connect('window-left-monitor', this.onWindowEnteredOrLeft.bind(this)); ++ } ++ ++ this._titleWindowChangeId = 0; ++ this._minimizedWindowChangeId = 0; ++ } else { ++ this._titleWindowChangeId = this.window.connect('notify::title', ++ Lang.bind(this, this._updateWindowTitle)); ++ ++ this._minimizedWindowChangeId = this.window.connect('notify::minimized', ++ Lang.bind(this, this._updateWindowTitleStyle)); ++ } ++ ++ this._scrollEventId = this.actor.connect('scroll-event', this._onMouseScroll.bind(this)); ++ ++ this._overviewWindowDragEndId = Main.overview.connect('window-drag-end', ++ Lang.bind(this, this._onOverviewWindowDragEnd)); ++ ++ this._switchWorkspaceId = global.window_manager.connect('switch-workspace', ++ Lang.bind(this, this._onSwitchWorkspace)); ++ ++ this._hoverChangeId = this.actor.connect('notify::hover', () => this._onAppIconHoverChanged()); ++ ++ this._dtpSettingsSignalIds = [ ++ Me.settings.connect('changed::animate-appicon-hover', Lang.bind(this, this._onAnimateAppiconHoverChanged)), ++ Me.settings.connect('changed::dot-position', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-size', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-style-focused', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-style-unfocused', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-dominant', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-override', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-1', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-2', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-3', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-4', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-unfocused-different', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-unfocused-1', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-unfocused-2', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-unfocused-3', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::dot-color-unfocused-4', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::focus-highlight', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::focus-highlight-dominant', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::focus-highlight-color', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::focus-highlight-opacity', Lang.bind(this, this._settingsChangeRefresh)), ++ Me.settings.connect('changed::group-apps-label-font-size', Lang.bind(this, this._updateWindowTitleStyle)), ++ Me.settings.connect('changed::group-apps-label-font-weight', Lang.bind(this, this._updateWindowTitleStyle)), ++ Me.settings.connect('changed::group-apps-label-font-color', Lang.bind(this, this._updateWindowTitleStyle)), ++ Me.settings.connect('changed::group-apps-label-font-color-minimized', Lang.bind(this, this._updateWindowTitleStyle)), ++ Me.settings.connect('changed::group-apps-label-max-width', Lang.bind(this, this._updateWindowTitleStyle)), ++ Me.settings.connect('changed::group-apps-use-fixed-width', Lang.bind(this, this._updateWindowTitleStyle)), ++ Me.settings.connect('changed::group-apps-underline-unfocused', Lang.bind(this, this._settingsChangeRefresh)) ++ ] ++ ++ this.forcedOverview = false; ++ ++ this._progressIndicator = new Progress.ProgressIndicator(this, panel.progressManager); ++ ++ this._numberOverlay(); ++ }, ++ ++ getDragActor: function() { ++ return this.app.create_icon_texture(this.dtpPanel.taskbar.iconSize); ++ }, ++ ++ // Used by TaskbarItemContainer to animate appIcons on hover ++ getCloneButton: function() { ++ // The source of the clone is this._container, ++ // using this.actor directly would break DnD style. ++ let clone = new Clutter.Clone({ ++ source: this.actor.child, ++ x: this.actor.child.x, y: this.actor.child.y, ++ width: this.actor.child.width, height: this.actor.child.height, ++ pivot_point: new Utils.getPoint({ x: 0.5, y: 0.5 }), ++ opacity: 255, ++ reactive: false, ++ x_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER, ++ }); ++ ++ // "clone" of this.actor ++ return new St.Button({ ++ child: clone, ++ x: this.actor.x, y: this.actor.y, ++ width: this.actor.width, height: this.actor.height, ++ reactive: false, ++ }); ++ }, ++ ++ shouldShowTooltip: function() { ++ if (!Me.settings.get_boolean('show-tooltip') || ++ (!this.isLauncher && Me.settings.get_boolean("show-window-previews") && ++ this.getAppIconInterestingWindows().length > 0)) { ++ return false; ++ } else { ++ return this.actor.hover && !this.window && ++ (!this._menu || !this._menu.isOpen) && ++ (this._previewMenu.getCurrentAppIcon() !== this); ++ } ++ }, ++ ++ _onAppIconHoverChanged: function() { ++ if (!Me.settings.get_boolean('show-window-previews') || ++ (!this.window && !this._nWindows)) { ++ return; ++ } ++ ++ if (this.actor.hover) { ++ this._previewMenu.requestOpen(this); ++ } else { ++ this._previewMenu.requestClose(); ++ } ++ }, ++ ++ _onDestroy: function() { ++ this.callParent('_onDestroy'); ++ this._destroyed = true; ++ ++ this._timeoutsHandler.destroy(); ++ ++ this._previewMenu.close(true); ++ ++ // Disconect global signals ++ // stateChangedId is already handled by parent) ++ ++ if(this._overviewWindowDragEndId) ++ Main.overview.disconnect(this._overviewWindowDragEndId); ++ ++ if(this._focusWindowChangedId) ++ global.display.disconnect(this._focusWindowChangedId); ++ ++ if(this._titleWindowChangeId) ++ this.window.disconnect(this._titleWindowChangeId); ++ ++ if(this._minimizedWindowChangeId) ++ this.window.disconnect(this._minimizedWindowChangeId); ++ ++ if (this._windowEnteredMonitorId) { ++ Utils.DisplayWrapper.getScreen().disconnect(this._windowEnteredMonitorId); ++ Utils.DisplayWrapper.getScreen().disconnect(this._windowLeftMonitorId); ++ } ++ ++ if(this._switchWorkspaceId) ++ global.window_manager.disconnect(this._switchWorkspaceId); ++ ++ if(this._scaleFactorChangedId) ++ Utils.getStageTheme().disconnect(this._scaleFactorChangedId); ++ ++ if (this._hoverChangeId) { ++ this.actor.disconnect(this._hoverChangeId); ++ } ++ ++ if (this._scrollEventId) { ++ this.actor.disconnect(this._scrollEventId); ++ } ++ ++ for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) { ++ Me.settings.disconnect(this._dtpSettingsSignalIds[i]); ++ } ++ }, ++ ++ onWindowsChanged: function() { ++ this._updateWindows(); ++ this.updateIcon(); ++ }, ++ ++ onWindowEnteredOrLeft: function() { ++ if (this._checkIfFocusedApp()) { ++ this._updateWindows(); ++ this._displayProperIndicator(); ++ } ++ }, ++ ++ updateTitleStyle: function() { ++ this._updateWindowTitleStyle(); ++ }, ++ ++ // Update indicator and target for minimization animation ++ updateIcon: function() { ++ ++ // If (for unknown reason) the actor is not on the stage the reported size ++ // and position are random values, which might exceeds the integer range ++ // resulting in an error when assigned to the a rect. This is a more like ++ // a workaround to prevent flooding the system with errors. ++ if (this.actor.get_stage() == null) ++ return; ++ ++ let rect = new Meta.Rectangle(); ++ ++ [rect.x, rect.y] = this.actor.get_transformed_position(); ++ [rect.width, rect.height] = this.actor.get_transformed_size(); ++ ++ let windows = this.window ? [this.window] : this.getAppIconInterestingWindows(true); ++ windows.forEach(function(w) { ++ w.set_icon_geometry(rect); ++ }); ++ }, ++ ++ _onAnimateAppiconHoverChanged: function() { ++ if (Me.settings.get_boolean('animate-appicon-hover')) { ++ this._container.add_style_class_name('animate-appicon-hover'); ++ ++ // Workaround to prevent scaled icon from being ugly when it is animated on hover. ++ // It increases the "resolution" of the icon without changing the icon size. ++ this.icon.createIcon = (iconSize) => this.app.create_icon_texture(2 * iconSize); ++ this._iconIconBinActorAddedId = this.icon._iconBin.connect('actor-added', () => { ++ if (this.icon._iconBin.child.mapped) { ++ this.icon._iconBin.child.set_size(this.icon.iconSize, this.icon.iconSize); ++ } else { ++ let iconMappedId = this.icon._iconBin.child.connect('notify::mapped', () => { ++ this.icon._iconBin.child.set_size(this.icon.iconSize, this.icon.iconSize); ++ this.icon._iconBin.child.disconnect(iconMappedId); ++ }); ++ } ++ }); ++ if (this.icon._iconBin.child) ++ this.icon._createIconTexture(this.icon.iconSize); ++ } else { ++ this._container.remove_style_class_name('animate-appicon-hover'); ++ ++ if (this._iconIconBinActorAddedId) { ++ this.icon._iconBin.disconnect(this._iconIconBinActorAddedId); ++ this._iconIconBinActorAddedId = 0; ++ this.icon.createIcon = Lang.bind(this, this._createIcon); ++ } ++ } ++ }, ++ ++ _onMouseScroll: function(actor, event) { ++ let scrollAction = Me.settings.get_string('scroll-icon-action'); ++ ++ if (scrollAction === 'PASS_THROUGH') { ++ return this.dtpPanel._onPanelMouseScroll(actor, event); ++ } else if (scrollAction === 'NOTHING' || (!this.window && !this._nWindows)) { ++ return; ++ } ++ ++ let direction = Utils.getMouseScrollDirection(event); ++ ++ if (direction && !this._timeoutsHandler.getId(T2)) { ++ this._timeoutsHandler.add([T2, Me.settings.get_int('scroll-icon-delay'), () => {}]); ++ ++ let windows = this.getAppIconInterestingWindows(); ++ ++ windows.sort(Taskbar.sortWindowsCompareFunction); ++ Utils.activateSiblingWindow(windows, direction, this.window); ++ } ++ }, ++ ++ _showDots: function() { ++ // Just update style if dots already exist ++ if (this._focusedDots && this._unfocusedDots) { ++ this._updateWindows(); ++ return; ++ } ++ ++ if (!this._isGroupApps) { ++ this._focusedDots = new St.Widget({ ++ layout_manager: new Clutter.BinLayout(), ++ x_expand: true, y_expand: true, ++ visible: false ++ }); ++ ++ let mappedId = this.actor.connect('notify::mapped', () => { ++ this._displayProperIndicator(); ++ this.actor.disconnect(mappedId); ++ }); ++ } else { ++ this._focusedDots = new St.DrawingArea(), ++ this._unfocusedDots = new St.DrawingArea(); ++ this._focusedDots._tweeningToSize = null, ++ this._unfocusedDots._tweeningToSize = null; ++ ++ this._focusedDots.connect('repaint', Lang.bind(this, function() { ++ if(this._dashItemContainer.animatingOut) { ++ // don't draw and trigger more animations if the icon is in the middle of ++ // being added to the panel ++ return; ++ } ++ this._drawRunningIndicator(this._focusedDots, Me.settings.get_string('dot-style-focused'), true); ++ this._displayProperIndicator(); ++ })); ++ ++ this._unfocusedDots.connect('repaint', Lang.bind(this, function() { ++ if(this._dashItemContainer.animatingOut) { ++ // don't draw and trigger more animations if the icon is in the middle of ++ // being added to the panel ++ return; ++ } ++ this._drawRunningIndicator(this._unfocusedDots, Me.settings.get_string('dot-style-unfocused'), false); ++ this._displayProperIndicator(); ++ })); ++ ++ this._dotsContainer.add_child(this._unfocusedDots); ++ ++ this._updateWindows(); ++ ++ this._timeoutsHandler.add([T3, 0, () => { ++ this._resetDots(); ++ this._displayProperIndicator(); ++ }]); ++ } ++ ++ this._dotsContainer.add_child(this._focusedDots); ++ }, ++ ++ _resetDots: function() { ++ let position = Me.settings.get_string('dot-position'); ++ let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM; ++ ++ [this._focusedDots, this._unfocusedDots].forEach(d => { ++ d._tweeningToSize = null; ++ d.set_size(-1, -1); ++ d.x_expand = d.y_expand = false; ++ ++ d[isHorizontalDots ? 'width' : 'height'] = 1; ++ d[(isHorizontalDots ? 'y' : 'x') + '_expand'] = true; ++ }); ++ }, ++ ++ _settingsChangeRefresh: function() { ++ if (this._isGroupApps) { ++ this._updateWindows(); ++ this._resetDots(); ++ this._focusedDots.queue_repaint(); ++ this._unfocusedDots.queue_repaint(); ++ } ++ ++ this._displayProperIndicator(true); ++ }, ++ ++ _updateWindowTitleStyle: function() { ++ if (this._windowTitle) { ++ let useFixedWidth = Me.settings.get_boolean('group-apps-use-fixed-width'); ++ let variableWidth = !useFixedWidth || this.dtpPanel.checkIfVertical() || this.dtpPanel.taskbar.fullScrollView; ++ let fontWeight = Me.settings.get_string('group-apps-label-font-weight'); ++ let fontScale = Me.desktopSettings.get_double('text-scaling-factor'); ++ let fontColor = this.window.minimized ? ++ Me.settings.get_string('group-apps-label-font-color-minimized') : ++ Me.settings.get_string('group-apps-label-font-color'); ++ let scaleFactor = Utils.getScaleFactor(); ++ let maxLabelWidth = Me.settings.get_int('group-apps-label-max-width') * scaleFactor; ++ ++ this._windowTitle[(maxLabelWidth > 0 ? 'show' : 'hide')](); ++ ++ this._windowTitle.clutter_text.natural_width = useFixedWidth ? maxLabelWidth : 0; ++ this._windowTitle.clutter_text.natural_width_set = useFixedWidth; ++ this._windowTitle.set_width(variableWidth ? -1 : maxLabelWidth + TITLE_RIGHT_PADDING * scaleFactor); ++ ++ this._windowTitle.set_style('font-size: ' + Me.settings.get_int('group-apps-label-font-size') * fontScale + 'px;' + ++ 'font-weight: ' + fontWeight + ';' + ++ (useFixedWidth ? '' : 'max-width: ' + maxLabelWidth + 'px;') + ++ 'color: ' + fontColor); ++ } ++ }, ++ ++ _updateWindowTitle: function() { ++ if (this._windowTitle.text != this.window.title) { ++ this._windowTitle.text = (this.window.title ? this.window.title : this.app.get_name()).replace(/\r?\n|\r/g, '').trim(); ++ ++ if (this._focusedDots) { ++ this._displayProperIndicator(); ++ } ++ } ++ }, ++ ++ _setIconStyle: function(isFocused) { ++ let inlineStyle = 'margin: 0;'; ++ ++ if(Me.settings.get_boolean('focus-highlight') && ++ this._checkIfFocusedApp() && !this.isLauncher && ++ (!this.window || isFocused) && !this._isThemeProvidingIndicator() && this._checkIfMonitorHasFocus()) { ++ let focusedDotStyle = Me.settings.get_string('dot-style-focused'); ++ let isWide = this._isWideDotStyle(focusedDotStyle); ++ let pos = Me.settings.get_string('dot-position'); ++ let highlightMargin = isWide ? Me.settings.get_int('dot-size') : 0; ++ ++ if(!this.window) { ++ let containerWidth = this._dtpIconContainer.get_width() / Utils.getScaleFactor();; ++ let backgroundSize = containerWidth + "px " + ++ (containerWidth - (pos == DOT_POSITION.BOTTOM ? highlightMargin : 0)) + "px;"; ++ ++ if (focusedDotStyle == DOT_STYLE.CILIORA || focusedDotStyle == DOT_STYLE.SEGMENTED) ++ highlightMargin += 1; ++ ++ if (this._nWindows > 1 && focusedDotStyle == DOT_STYLE.METRO) { ++ let bgSvg = '/img/highlight_stacked_bg'; ++ ++ if (pos == DOT_POSITION.LEFT || pos == DOT_POSITION.RIGHT) { ++ bgSvg += (this.dtpPanel.checkIfVertical() ? '_2' : '_3'); ++ } ++ ++ inlineStyle += "background-image: url('" + Me.path + bgSvg + ".svg');" + ++ "background-position: 0 " + (pos == DOT_POSITION.TOP ? highlightMargin : 0) + "px;" + ++ "background-size: " + backgroundSize; ++ } ++ } ++ ++ let highlightColor = this._getFocusHighlightColor(); ++ inlineStyle += "background-color: " + cssHexTocssRgba(highlightColor, Me.settings.get_int('focus-highlight-opacity') * 0.01); ++ } ++ ++ if(this._dotsContainer.get_style() != inlineStyle && this._dotsContainer.mapped) { ++ if (!this._isGroupApps) { ++ //when the apps are ungrouped, set the style synchronously so the icons don't jump around on taskbar redraw ++ this._dotsContainer.set_style(inlineStyle); ++ } else if (!this._timeoutsHandler.getId(T1)) { ++ //graphical glitches if i dont set this on a timeout ++ this._timeoutsHandler.add([T1, 0, () => this._dotsContainer.set_style(inlineStyle)]); ++ } ++ } ++ }, ++ ++ _checkIfFocusedApp: function() { ++ return tracker.focus_app == this.app; ++ }, ++ ++ _checkIfMonitorHasFocus: function() { ++ return global.display.focus_window && ++ (!Me.settings.get_boolean('multi-monitors') || // only check same monitor index if multi window is enabled. ++ !Me.settings.get_boolean('isolate-monitors') || ++ global.display.focus_window.get_monitor() === this.dtpPanel.monitor.index); ++ }, ++ ++ _setAppIconPadding: function() { ++ let padding = getIconPadding(this.dtpPanel.monitor.index); ++ let margin = Me.settings.get_int('appicon-margin'); ++ ++ this.actor.set_style('padding:' + (this.dtpPanel.checkIfVertical() ? margin + 'px 0' : '0 ' + margin + 'px;')); ++ this._iconContainer.set_style('padding: ' + padding + 'px;'); ++ }, ++ ++ popupMenu: function() { ++ this._removeMenuTimeout(); ++ this.actor.fake_release(); ++ ++ if (this._draggable) { ++ this._draggable.fakeRelease(); ++ } ++ ++ if (this.isDragged) { ++ return; ++ } ++ ++ if (!this._menu) { ++ this._menu = new taskbarSecondaryMenu(this, this.dtpPanel); ++ this._menu.connect('activate-window', Lang.bind(this, function (menu, window) { ++ this.activateWindow(window, Me.settings); ++ })); ++ this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) { ++ if (!isPoppedUp) ++ this._onMenuPoppedDown(); ++ })); ++ let id = Main.overview.connect('hiding', Lang.bind(this, function () { this._menu.close(); })); ++ this._menu.actor.connect('destroy', function() { ++ Main.overview.disconnect(id); ++ }); ++ ++ this._menuManager.addMenu(this._menu); ++ } ++ ++ this.emit('menu-state-changed', true); ++ ++ this._previewMenu.close(true); ++ ++ this.actor.set_hover(true); ++ this._menu.actor.add_style_class_name('dashtopanelSecondaryMenu'); ++ this._menu.popup(); ++ this._menuManager.ignoreRelease(); ++ this.emit('sync-tooltip'); ++ ++ return false; ++ }, ++ ++ _onFocusAppChanged: function(windowTracker) { ++ this._displayProperIndicator(true); ++ }, ++ ++ _onOverviewWindowDragEnd: function(windowTracker) { ++ this._timeoutsHandler.add([T4, 0, () => this._displayProperIndicator()]); ++ }, ++ ++ _onSwitchWorkspace: function(windowTracker) { ++ if (this._isGroupApps) { ++ this._timeoutsHandler.add([T5, 0, () => this._displayProperIndicator(true)]); ++ } else { ++ this._displayProperIndicator(); ++ } ++ }, ++ ++ _displayProperIndicator: function (force) { ++ let isFocused = this._isFocusedWindow(); ++ let position = Me.settings.get_string('dot-position'); ++ let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM; ++ ++ this._setIconStyle(isFocused); ++ ++ if(!this._isGroupApps) { ++ if (this.window && (Me.settings.get_boolean('group-apps-underline-unfocused') || isFocused)) { ++ let align = Clutter.ActorAlign[position == DOT_POSITION.TOP || position == DOT_POSITION.LEFT ? 'START' : 'END']; ++ ++ this._focusedDots.set_size(0, 0); ++ this._focusedDots[isHorizontalDots ? 'height' : 'width'] = this._getRunningIndicatorSize(); ++ ++ this._focusedDots.y_align = this._focusedDots.x_align = Clutter.ActorAlign.FILL; ++ this._focusedDots[(isHorizontalDots ? 'y' : 'x') + '_align'] = align; ++ this._focusedDots.background_color = this._getRunningIndicatorColor(isFocused); ++ this._focusedDots.show(); ++ } else if (this._focusedDots.visible) { ++ this._focusedDots.hide(); ++ } ++ } else { ++ let sizeProp = isHorizontalDots ? 'width' : 'height'; ++ let containerSize = this._container[sizeProp]; ++ let focusedDotStyle = Me.settings.get_string('dot-style-focused'); ++ let unfocusedDotStyle = Me.settings.get_string('dot-style-unfocused'); ++ let focusedIsWide = this._isWideDotStyle(focusedDotStyle); ++ let unfocusedIsWide = this._isWideDotStyle(unfocusedDotStyle); ++ ++ let newFocusedDotsSize = 0; ++ let newFocusedDotsOpacity = 0; ++ let newUnfocusedDotsSize = 0; ++ let newUnfocusedDotsOpacity = 0; ++ ++ isFocused = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus(); ++ ++ this._timeoutsHandler.add([T6, 0, () => { ++ if (!this._destroyed) { ++ if(isFocused) ++ this.actor.add_style_class_name('focused'); ++ else ++ this.actor.remove_style_class_name('focused'); ++ } ++ }]); ++ ++ if(focusedIsWide) { ++ newFocusedDotsSize = (isFocused && this._nWindows > 0) ? containerSize : 0; ++ newFocusedDotsOpacity = 255; ++ } else { ++ newFocusedDotsSize = containerSize; ++ newFocusedDotsOpacity = (isFocused && this._nWindows > 0) ? 255 : 0; ++ } ++ ++ if(unfocusedIsWide) { ++ newUnfocusedDotsSize = (!isFocused && this._nWindows > 0) ? containerSize : 0; ++ newUnfocusedDotsOpacity = 255; ++ } else { ++ newUnfocusedDotsSize = containerSize; ++ newUnfocusedDotsOpacity = (!isFocused && this._nWindows > 0) ? 255 : 0; ++ } ++ ++ // Only animate if... ++ // animation is enabled in settings ++ // AND (going from a wide style to a narrow style indicator or vice-versa ++ // OR going from an open app to a closed app or vice versa) ++ if(Me.settings.get_boolean('animate-app-switch') && ++ ((focusedIsWide != unfocusedIsWide) || ++ (this._focusedDots[sizeProp] != newUnfocusedDotsSize || this._unfocusedDots[sizeProp] != newFocusedDotsSize))) { ++ this._animateDotDisplay(this._focusedDots, newFocusedDotsSize, this._unfocusedDots, newUnfocusedDotsOpacity, force, sizeProp); ++ this._animateDotDisplay(this._unfocusedDots, newUnfocusedDotsSize, this._focusedDots, newFocusedDotsOpacity, force, sizeProp); ++ } else { ++ this._focusedDots.opacity = newFocusedDotsOpacity; ++ this._unfocusedDots.opacity = newUnfocusedDotsOpacity; ++ this._focusedDots[sizeProp] = newFocusedDotsSize; ++ this._unfocusedDots[sizeProp] = newUnfocusedDotsSize; ++ } ++ } ++ }, ++ ++ _animateDotDisplay: function (dots, newSize, otherDots, newOtherOpacity, force, sizeProp) { ++ if((dots[sizeProp] != newSize && dots._tweeningToSize !== newSize) || force) { ++ let tweenOpts = { ++ time: Taskbar.DASH_ANIMATION_TIME, ++ transition: 'easeInOutCubic', ++ onComplete: Lang.bind(this, function() { ++ if(newOtherOpacity > 0) ++ otherDots.opacity = newOtherOpacity; ++ dots._tweeningToSize = null; ++ }) ++ }; ++ ++ if(newOtherOpacity == 0) ++ otherDots.opacity = newOtherOpacity; ++ ++ tweenOpts[sizeProp] = newSize; ++ dots._tweeningToSize = newSize; ++ ++ Utils.animate(dots, tweenOpts); ++ } ++ }, ++ ++ _isFocusedWindow: function() { ++ let focusedWindow = global.display.focus_window; ++ ++ while (focusedWindow) { ++ if (focusedWindow == this.window) { ++ return true; ++ } ++ ++ focusedWindow = focusedWindow.get_transient_for(); ++ } ++ ++ return false; ++ }, ++ ++ _isWideDotStyle: function(dotStyle) { ++ return dotStyle == DOT_STYLE.SEGMENTED || ++ dotStyle == DOT_STYLE.CILIORA || ++ dotStyle == DOT_STYLE.METRO || ++ dotStyle == DOT_STYLE.SOLID; ++ }, ++ ++ _isThemeProvidingIndicator: function () { ++ // This is an attempt to determine if the theme is providing their own ++ // running indicator by way of a border image on the icon, for example in ++ // the theme Ciliora ++ return (this.icon.actor.get_stage() && ++ this.icon.actor.get_theme_node().get_border_image()); ++ }, ++ ++ activate: function(button, handleAsGrouped) { ++ let event = Clutter.get_current_event(); ++ let modifiers = event ? event.get_state() : 0; ++ ++ // Only consider SHIFT and CONTROL as modifiers (exclude SUPER, CAPS-LOCK, etc.) ++ modifiers = modifiers & (Clutter.ModifierType.SHIFT_MASK | Clutter.ModifierType.CONTROL_MASK); ++ ++ // We don't change the CTRL-click behaviour: in such case we just chain ++ // up the parent method and return. ++ if (modifiers & Clutter.ModifierType.CONTROL_MASK) { ++ // Keep default behaviour: launch new window ++ // By calling the parent method I make it compatible ++ // with other extensions tweaking ctrl + click ++ this.callParent('activate', button); ++ return; ++ } ++ ++ // We check what type of click we have and if the modifier SHIFT is ++ // being used. We then define what buttonAction should be for this ++ // event. ++ let buttonAction = 0; ++ if (button && button == 2 ) { ++ if (modifiers & Clutter.ModifierType.SHIFT_MASK) ++ buttonAction = Me.settings.get_string('shift-middle-click-action'); ++ else ++ buttonAction = Me.settings.get_string('middle-click-action'); ++ } ++ else if (button && button == 1) { ++ if (modifiers & Clutter.ModifierType.SHIFT_MASK) ++ buttonAction = Me.settings.get_string('shift-click-action'); ++ else ++ buttonAction = Me.settings.get_string('click-action'); ++ } ++ ++ let appCount = this.getAppIconInterestingWindows().length; ++ let previewedAppIcon = this._previewMenu.getCurrentAppIcon(); ++ this._previewMenu.close(Me.settings.get_boolean('window-preview-hide-immediate-click')); ++ ++ // We check if the app is running, and that the # of windows is > 0 in ++ // case we use workspace isolation, ++ let appIsRunning = this.app.state == Shell.AppState.RUNNING && appCount > 0; ++ ++ // We customize the action only when the application is already running ++ if (appIsRunning && !this.isLauncher) { ++ if (this.window && !handleAsGrouped) { ++ //ungrouped applications behaviors ++ switch (buttonAction) { ++ case 'RAISE': case 'CYCLE': case 'CYCLE-MIN': case 'MINIMIZE': case 'TOGGLE-SHOWPREVIEW': case 'TOGGLE-CYCLE': ++ if (!Main.overview._shown && ++ (buttonAction == 'MINIMIZE' || buttonAction == 'TOGGLE-SHOWPREVIEW' || buttonAction == 'TOGGLE-CYCLE' || buttonAction == 'CYCLE-MIN') && ++ (this._isFocusedWindow() || (buttonAction == 'MINIMIZE' && (button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK)))) { ++ this.window.minimize(); ++ } else { ++ Main.activateWindow(this.window); ++ } ++ ++ break; ++ ++ case "LAUNCH": ++ this._launchNewInstance(); ++ break; ++ ++ case "QUIT": ++ this.window.delete(global.get_current_time()); ++ break; ++ } ++ } else { ++ //grouped application behaviors ++ let monitor = this.dtpPanel.monitor; ++ let appHasFocus = this._checkIfFocusedApp() && this._checkIfMonitorHasFocus(); ++ ++ switch (buttonAction) { ++ case "RAISE": ++ activateAllWindows(this.app, monitor); ++ break; ++ ++ case "LAUNCH": ++ this._launchNewInstance(); ++ break; ++ ++ case "MINIMIZE": ++ // In overview just activate the app, unless the acion is explicitely ++ // requested with a keyboard modifier ++ if (!Main.overview._shown || modifiers){ ++ // If we have button=2 or a modifier, allow minimization even if ++ // the app is not focused ++ if (appHasFocus || button == 2 || modifiers & Clutter.ModifierType.SHIFT_MASK) { ++ // minimize all windows on double click and always in the case of primary click without ++ // additional modifiers ++ let all_windows = (button == 1 && ! modifiers) || event.get_click_count() > 1; ++ minimizeWindow(this.app, all_windows, monitor); ++ } ++ else ++ activateAllWindows(this.app, monitor); ++ } ++ else ++ this.app.activate(); ++ break; ++ ++ case "CYCLE": ++ if (!Main.overview._shown){ ++ if (appHasFocus) ++ cycleThroughWindows(this.app, false, false, monitor); ++ else { ++ activateFirstWindow(this.app, monitor); ++ } ++ } ++ else ++ this.app.activate(); ++ break; ++ case "CYCLE-MIN": ++ if (!Main.overview._shown){ ++ if (appHasFocus || (recentlyClickedApp == this.app && recentlyClickedAppWindows[recentlyClickedAppIndex % recentlyClickedAppWindows.length] == "MINIMIZE")) ++ cycleThroughWindows(this.app, false, true, monitor); ++ else { ++ activateFirstWindow(this.app, monitor); ++ } ++ } ++ else ++ this.app.activate(); ++ break; ++ case "TOGGLE-SHOWPREVIEW": ++ if (!Main.overview._shown) { ++ if (appCount == 1) { ++ if (appHasFocus) ++ minimizeWindow(this.app, false, monitor); ++ else ++ activateFirstWindow(this.app, monitor); ++ } else { ++ if (event.get_click_count() > 1) { ++ // minimize all windows if double clicked ++ minimizeWindow(this.app, true, monitor); ++ } else if (previewedAppIcon != this) { ++ this._previewMenu.open(this); ++ } ++ ++ this.emit('sync-tooltip'); ++ } ++ } ++ else ++ this.app.activate(); ++ break; ++ case "TOGGLE-CYCLE": ++ if (!Main.overview._shown) { ++ if (appCount == 1) { ++ if (appHasFocus) ++ minimizeWindow(this.app, false, monitor); ++ else ++ activateFirstWindow(this.app, monitor); ++ } else { ++ cycleThroughWindows(this.app, false, false, monitor); ++ } ++ } ++ else ++ this.app.activate(); ++ break; ++ case "QUIT": ++ closeAllWindows(this.app, monitor); ++ break; ++ } ++ } ++ } ++ else { ++ this._launchNewInstance(); ++ } ++ ++ Main.overview.hide(); ++ }, ++ ++ _launchNewInstance: function() { ++ if (this.app.can_open_new_window()) { ++ let appActions = this.app.get_app_info().list_actions(); ++ let newWindowIndex = appActions.indexOf('new-window'); ++ ++ if(Me.settings.get_boolean('animate-window-launch')) { ++ this.animateLaunch(); ++ } ++ ++ if (newWindowIndex < 0) { ++ this.app.open_new_window(-1); ++ } else { ++ this.app.launch_action(appActions[newWindowIndex], global.get_current_time(), -1); ++ } ++ } else { ++ let windows = this.window ? [this.window] : this.app.get_windows(); ++ ++ if (windows.length) { ++ Main.activateWindow(windows[0]); ++ } else { ++ this.app.activate(); ++ } ++ } ++ }, ++ ++ _updateWindows: function() { ++ let windows = [this.window]; ++ ++ if (!this.window) { ++ windows = this.getAppIconInterestingWindows(); ++ ++ this._nWindows = windows.length; ++ ++ for (let i = 1; i <= MAX_INDICATORS; i++){ ++ let className = 'running'+i; ++ if(i != this._nWindows) ++ this.actor.remove_style_class_name(className); ++ else ++ this.actor.add_style_class_name(className); ++ } ++ } ++ ++ this._previewMenu.update(this, windows); ++ }, ++ ++ _getRunningIndicatorCount: function() { ++ return Math.min(this._nWindows, MAX_INDICATORS); ++ }, ++ ++ _getRunningIndicatorSize: function() { ++ return Me.settings.get_int('dot-size') * Utils.getScaleFactor(); ++ }, ++ ++ _getRunningIndicatorColor: function(isFocused) { ++ let color; ++ const fallbackColor = new Clutter.Color({ red: 82, green: 148, blue: 226, alpha: 255 }); ++ ++ if (Me.settings.get_boolean('dot-color-dominant')) { ++ let dce = new Utils.DominantColorExtractor(this.app); ++ let palette = dce._getColorPalette(); ++ if (palette) { ++ color = Clutter.color_from_string(palette.original)[1]; ++ } else { // unable to determine color, fall back to theme ++ let themeNode = this._dot.get_theme_node(); ++ color = themeNode.get_background_color(); ++ ++ // theme didn't provide one, use a default ++ if(color.alpha == 0) color = fallbackColor; ++ } ++ } else if(Me.settings.get_boolean('dot-color-override')) { ++ let dotColorSettingPrefix = 'dot-color-'; ++ ++ if(!isFocused && Me.settings.get_boolean('dot-color-unfocused-different')) ++ dotColorSettingPrefix = 'dot-color-unfocused-'; ++ ++ color = Clutter.color_from_string(Me.settings.get_string(dotColorSettingPrefix + (this._getRunningIndicatorCount() || 1) ))[1]; ++ } else { ++ // Re-use the style - background color, and border width and color - ++ // of the default dot ++ let themeNode = this._dot.get_theme_node(); ++ color = themeNode.get_background_color(); ++ ++ // theme didn't provide one, use a default ++ if(color.alpha == 0) color = fallbackColor; ++ } ++ ++ return color; ++ }, ++ ++ _getFocusHighlightColor: function() { ++ if (Me.settings.get_boolean('focus-highlight-dominant')) { ++ let dce = new Utils.DominantColorExtractor(this.app); ++ let palette = dce._getColorPalette(); ++ if (palette) return palette.original; ++ } ++ return Me.settings.get_string('focus-highlight-color'); ++ }, ++ ++ _drawRunningIndicator: function(area, type, isFocused) { ++ let n = this._getRunningIndicatorCount(); ++ ++ if (!n) { ++ return; ++ } ++ ++ let position = Me.settings.get_string('dot-position'); ++ let isHorizontalDots = position == DOT_POSITION.TOP || position == DOT_POSITION.BOTTOM; ++ let bodyColor = this._getRunningIndicatorColor(isFocused); ++ let [areaWidth, areaHeight] = area.get_surface_size(); ++ let cr = area.get_context(); ++ let size = this._getRunningIndicatorSize(); ++ ++ let areaSize = areaWidth; ++ let startX = 0; ++ let startY = 0; ++ ++ if (isHorizontalDots) { ++ if (position == DOT_POSITION.BOTTOM) { ++ startY = areaHeight - size; ++ } ++ } else { ++ areaSize = areaHeight; ++ ++ if (position == DOT_POSITION.RIGHT) { ++ startX = areaWidth - size; ++ } ++ } ++ ++ if (type == DOT_STYLE.SOLID || type == DOT_STYLE.METRO) { ++ if (type == DOT_STYLE.SOLID || n <= 1) { ++ cr.translate(startX, startY); ++ Clutter.cairo_set_source_color(cr, bodyColor); ++ cr.newSubPath(); ++ cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [areaSize, size] : [size, areaSize])); ++ cr.fill(); ++ } else { ++ let blackenedLength = (1 / 48) * areaSize; // need to scale with the SVG for the stacked highlight ++ let darkenedLength = isFocused ? (2 / 48) * areaSize : (10 / 48) * areaSize; ++ let blackenedColor = bodyColor.shade(.3); ++ let darkenedColor = bodyColor.shade(.7); ++ let solidDarkLength = areaSize - darkenedLength; ++ let solidLength = solidDarkLength - blackenedLength; ++ ++ cr.translate(startX, startY); ++ ++ Clutter.cairo_set_source_color(cr, bodyColor); ++ cr.newSubPath(); ++ cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [solidLength, size] : [size, solidLength])); ++ cr.fill(); ++ Clutter.cairo_set_source_color(cr, blackenedColor); ++ cr.newSubPath(); ++ cr.rectangle.apply(cr, isHorizontalDots ? [solidLength, 0, 1, size] : [0, solidLength, size, 1]); ++ cr.fill(); ++ Clutter.cairo_set_source_color(cr, darkenedColor); ++ cr.newSubPath(); ++ cr.rectangle.apply(cr, isHorizontalDots ? [solidDarkLength, 0, darkenedLength, size] : [0, solidDarkLength, size, darkenedLength]); ++ cr.fill(); ++ } ++ } else { ++ let spacing = Math.ceil(areaSize / 18); // separation between the indicators ++ let length; ++ let dist; ++ let indicatorSize; ++ let translate; ++ let preDraw = () => {}; ++ let draw; ++ let drawDash = (i, dashLength) => { ++ dist = i * dashLength + i * spacing; ++ cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0, dashLength, size] : [0, dist, size, dashLength])); ++ }; ++ ++ switch (type) { ++ case DOT_STYLE.CILIORA: ++ spacing = size; ++ length = areaSize - (size * (n - 1)) - (spacing * (n - 1)); ++ translate = () => cr.translate(startX, startY); ++ preDraw = () => { ++ cr.newSubPath(); ++ cr.rectangle.apply(cr, [0, 0].concat(isHorizontalDots ? [length, size] : [size, length])); ++ }; ++ draw = i => { ++ dist = length + (i * spacing) + ((i - 1) * size); ++ cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size])); ++ }; ++ break; ++ case DOT_STYLE.DOTS: ++ let radius = size / 2; ++ ++ translate = () => { ++ indicatorSize = Math.floor((areaSize - n * size - (n - 1) * spacing) / 2); ++ cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]); ++ } ++ draw = i => { ++ dist = (2 * i + 1) * radius + i * spacing; ++ cr.arc.apply(cr, (isHorizontalDots ? [dist, radius] : [radius, dist]).concat([radius, 0, 2 * Math.PI])); ++ }; ++ break; ++ case DOT_STYLE.SQUARES: ++ translate = () => { ++ indicatorSize = Math.floor((areaSize - n * size - (n - 1) * spacing) / 2); ++ cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]); ++ } ++ draw = i => { ++ dist = i * size + i * spacing; ++ cr.rectangle.apply(cr, (isHorizontalDots ? [dist, 0] : [0, dist]).concat([size, size])); ++ }; ++ break; ++ case DOT_STYLE.DASHES: ++ length = Math.floor(areaSize / 4) - spacing; ++ translate = () => { ++ indicatorSize = Math.floor((areaSize - n * length - (n - 1) * spacing) / 2); ++ cr.translate.apply(cr, isHorizontalDots ? [indicatorSize, startY] : [startX, indicatorSize]); ++ } ++ draw = i => drawDash(i, length); ++ break; ++ case DOT_STYLE.SEGMENTED: ++ length = Math.ceil((areaSize - ((n - 1) * spacing)) / n); ++ translate = () => cr.translate(startX, startY); ++ draw = i => drawDash(i, length); ++ break; ++ } ++ ++ translate(); ++ ++ Clutter.cairo_set_source_color(cr, bodyColor); ++ preDraw(); ++ for (let i = 0; i < n; i++) { ++ cr.newSubPath(); ++ draw(i); ++ } ++ cr.fill(); ++ } ++ ++ cr.$dispose(); ++ }, ++ ++ _numberOverlay: function() { ++ // Add label for a Hot-Key visual aid ++ this._numberOverlayLabel = new St.Label({ style_class: 'badge' }); ++ this._numberOverlayBin = new St.Bin({ ++ child: this._numberOverlayLabel, y: 2 ++ }); ++ this._numberOverlayLabel.add_style_class_name('number-overlay'); ++ this._numberOverlayOrder = -1; ++ this._numberOverlayBin.hide(); ++ ++ this._dtpIconContainer.add_child(this._numberOverlayBin); ++ }, ++ ++ updateHotkeyNumberOverlay: function() { ++ this.updateNumberOverlay(this._numberOverlayBin, true); ++ }, ++ ++ updateNumberOverlay: function(bin, fixedSize) { ++ // We apply an overall scale factor that might come from a HiDPI monitor. ++ // Clutter dimensions are in physical pixels, but CSS measures are in logical ++ // pixels, so make sure to consider the scale. ++ // Set the font size to something smaller than the whole icon so it is ++ // still visible. The border radius is large to make the shape circular ++ let [minWidth, natWidth] = this._dtpIconContainer.get_preferred_width(-1); ++ let font_size = Math.round(Math.max(12, 0.3 * natWidth) / Utils.getScaleFactor()); ++ let size = Math.round(font_size * 1.3); ++ let label = bin.child; ++ let style = 'font-size: ' + font_size + 'px;' + ++ 'border-radius: ' + this.icon.iconSize + 'px;' + ++ 'height: ' + size +'px;'; ++ ++ if (fixedSize || label.get_text().length == 1) { ++ style += 'width: ' + size + 'px;'; ++ } else { ++ style += 'padding: 0 2px;'; ++ } ++ ++ bin.x = fixedSize ? natWidth - size - 2 : 2; ++ label.set_style(style); ++ }, ++ ++ setNumberOverlay: function(number) { ++ this._numberOverlayOrder = number; ++ this._numberOverlayLabel.set_text(number.toString()); ++ }, ++ ++ toggleNumberOverlay: function(activate) { ++ if (activate && this._numberOverlayOrder > -1) ++ this._numberOverlayBin.show(); ++ else ++ this._numberOverlayBin.hide(); ++ }, ++ ++ handleDragOver: function(source, actor, x, y, time) { ++ if (source == Main.xdndHandler) { ++ this._previewMenu.close(true); ++ } ++ ++ return DND.DragMotionResult.CONTINUE; ++ }, ++ ++ // Disable all DnD methods on gnome-shell 3.34 ++ _onDragBegin: function() {}, ++ _onDragEnd: function() {}, ++ acceptDrop: function() { return false; }, ++ ++ getAppIconInterestingWindows: function(isolateMonitors) { ++ return getInterestingWindows(this.app, this.dtpPanel.monitor, isolateMonitors); ++ } ++}); ++taskbarAppIcon.prototype.scaleAndFade = taskbarAppIcon.prototype.undoScaleAndFade = () => {}; ++ ++function minimizeWindow(app, param, monitor){ ++ // Param true make all app windows minimize ++ let windows = getInterestingWindows(app, monitor); ++ let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++ for (let i = 0; i < windows.length; i++) { ++ let w = windows[i]; ++ if (w.get_workspace() == current_workspace && w.showing_on_its_workspace()){ ++ w.minimize(); ++ // Just minimize one window. By specification it should be the ++ // focused window on the current workspace. ++ if(!param) ++ break; ++ } ++ } ++} ++ ++/* ++ * By default only non minimized windows are activated. ++ * This activates all windows in the current workspace. ++ */ ++function activateAllWindows(app, monitor){ ++ ++ // First activate first window so workspace is switched if needed, ++ // then activate all other app windows in the current workspace. ++ let windows = getInterestingWindows(app, monitor); ++ let w = windows[0]; ++ Main.activateWindow(w); ++ let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace_index(); ++ ++ if (windows.length <= 0) ++ return; ++ ++ for (let i = windows.length - 1; i >= 0; i--){ ++ if (windows[i].get_workspace().index() == activeWorkspace){ ++ Main.activateWindow(windows[i]); ++ } ++ } ++} ++ ++function activateFirstWindow(app, monitor){ ++ ++ let windows = getInterestingWindows(app, monitor); ++ Main.activateWindow(windows[0]); ++} ++ ++function cycleThroughWindows(app, reversed, shouldMinimize, monitor) { ++ // Store for a little amount of time last clicked app and its windows ++ // since the order changes upon window interaction ++ let MEMORY_TIME=3000; ++ ++ let app_windows = getInterestingWindows(app, monitor); ++ ++ if(shouldMinimize) ++ app_windows.push("MINIMIZE"); ++ ++ if (recentlyClickedAppLoopId > 0) ++ Mainloop.source_remove(recentlyClickedAppLoopId); ++ ++ recentlyClickedAppLoopId = Mainloop.timeout_add(MEMORY_TIME, resetRecentlyClickedApp); ++ ++ // If there isn't already a list of windows for the current app, ++ // or the stored list is outdated, use the current windows list. ++ if (!recentlyClickedApp || ++ recentlyClickedApp.get_id() != app.get_id() || ++ recentlyClickedAppWindows.length != app_windows.length || ++ recentlyClickedAppMonitorIndex != monitor.index) { ++ recentlyClickedApp = app; ++ recentlyClickedAppWindows = app_windows; ++ recentlyClickedAppIndex = 0; ++ recentlyClickedAppMonitorIndex = monitor.index; ++ } ++ ++ if (reversed) { ++ recentlyClickedAppIndex--; ++ if (recentlyClickedAppIndex < 0) recentlyClickedAppIndex = recentlyClickedAppWindows.length - 1; ++ } else { ++ recentlyClickedAppIndex++; ++ } ++ let index = recentlyClickedAppIndex % recentlyClickedAppWindows.length; ++ ++ if(recentlyClickedAppWindows[index] === "MINIMIZE") ++ minimizeWindow(app, true, monitor); ++ else ++ Main.activateWindow(recentlyClickedAppWindows[index]); ++} ++ ++function resetRecentlyClickedApp() { ++ if (recentlyClickedAppLoopId > 0) ++ Mainloop.source_remove(recentlyClickedAppLoopId); ++ ++ recentlyClickedAppLoopId=0; ++ recentlyClickedApp =null; ++ recentlyClickedAppWindows = null; ++ recentlyClickedAppIndex = 0; ++ recentlyClickedAppMonitorIndex = null; ++ ++ return false; ++} ++ ++function closeAllWindows(app, monitor) { ++ let windows = getInterestingWindows(app, monitor); ++ for (let i = 0; i < windows.length; i++) ++ windows[i].delete(global.get_current_time()); ++} ++ ++// Filter out unnecessary windows, for instance ++// nautilus desktop window. ++function getInterestingWindows(app, monitor, isolateMonitors) { ++ let windows = app.get_windows().filter(function(w) { ++ return !w.skip_taskbar; ++ }); ++ ++ // When using workspace or monitor isolation, we filter out windows ++ // that are not in the current workspace or on the same monitor as the appicon ++ if (Me.settings.get_boolean('isolate-workspaces')) ++ windows = windows.filter(function(w) { ++ return w.get_workspace().index() == Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace_index(); ++ }); ++ ++ if (monitor && Me.settings.get_boolean('multi-monitors') && (isolateMonitors || Me.settings.get_boolean('isolate-monitors'))) { ++ windows = windows.filter(function(w) { ++ return w.get_monitor() == monitor.index; ++ }); ++ } ++ ++ return windows; ++} ++ ++function cssHexTocssRgba(cssHex, opacity) { ++ var bigint = parseInt(cssHex.slice(1), 16); ++ var r = (bigint >> 16) & 255; ++ var g = (bigint >> 8) & 255; ++ var b = bigint & 255; ++ ++ return 'rgba(' + [r, g, b].join(',') + ',' + opacity + ')'; ++} ++ ++function getIconPadding(monitorIndex) { ++ let panelSize = PanelSettings.getPanelSize(Me.settings, monitorIndex); ++ let padding = Me.settings.get_int('appicon-padding'); ++ let availSize = panelSize - Taskbar.MIN_ICON_SIZE - panelSize % 2; ++ ++ if (padding * 2 > availSize) { ++ padding = availSize * .5; ++ } ++ ++ return padding; ++} ++ ++/** ++ * Extend AppIconMenu ++ * ++ * - set popup arrow side based on taskbar orientation ++ * - Add close windows option based on quitfromdash extension ++ * (https://github.com/deuill/shell-extension-quitfromdash) ++ */ ++ ++var taskbarSecondaryMenu = Utils.defineClass({ ++ Name: 'DashToPanel.SecondaryMenu', ++ Extends: AppDisplay.AppIconMenu, ++ ParentConstrParams: [[0]], ++ ++ _init: function(source, panel) { ++ // Damm it, there has to be a proper way of doing this... ++ // As I can't call the parent parent constructor (?) passing the side ++ // parameter, I overwite what I need later ++ this.callParent('_init', source); ++ ++ let side = panel.getPosition(); ++ // Change the initialized side where required. ++ this._arrowSide = side; ++ this._boxPointer._arrowSide = side; ++ this._boxPointer._userArrowSide = side; ++ }, ++ ++ // helper function for the quit windows abilities ++ _closeWindowInstance: function(metaWindow) { ++ metaWindow.delete(global.get_current_time()); ++ }, ++ ++ _dtpRedisplay: function(parentFunc) { ++ this.callParent(parentFunc); ++ ++ // Remove "Show Details" menu item ++ if(!Me.settings.get_boolean('secondarymenu-contains-showdetails')) { ++ let existingMenuItems = this._getMenuItems(); ++ for(let idx in existingMenuItems) { ++ if(existingMenuItems[idx].actor.label_actor.text == _("Show Details")) { ++ this.box.remove_child(existingMenuItems[idx].actor); ++ if(existingMenuItems[idx-1] instanceof PopupMenu.PopupSeparatorMenuItem) ++ this.box.remove_child(existingMenuItems[idx-1].actor); ++ break; ++ } ++ } ++ } ++ ++ // prepend items from the appMenu (for native gnome apps) ++ if(Me.settings.get_boolean('secondarymenu-contains-appmenu')) { ++ let appMenu = this._source.app.menu; ++ if(appMenu) { ++ let remoteMenu = new imports.ui.remoteMenu.RemoteMenu(this._source.actor, this._source.app.menu, this._source.app.action_group); ++ let appMenuItems = remoteMenu._getMenuItems(); ++ for(var i = 0, l = appMenuItems.length || 0; i < l; ++i) { ++ let menuItem = appMenuItems[i]; ++ let labelText = menuItem.actor.label_actor.text; ++ if(labelText == _("New Window") || labelText == _("Quit")) ++ continue; ++ ++ if(menuItem instanceof PopupMenu.PopupSeparatorMenuItem) ++ continue; ++ ++ // this ends up getting called multiple times, and bombing due to the signal id's being invalid ++ // on a 2nd pass. disconnect the base handler and attach our own that wraps the id's in if statements ++ menuItem.disconnect(menuItem._popupMenuDestroyId) ++ menuItem._popupMenuDestroyId = menuItem.connect('destroy', Lang.bind(this, function(menuItem) { ++ if(menuItem._popupMenuDestroyId) { ++ menuItem.disconnect(menuItem._popupMenuDestroyId); ++ menuItem._popupMenuDestroyId = 0; ++ } ++ if(menuItem._activateId) { ++ menuItem.disconnect(menuItem._activateId); ++ menuItem._activateId = 0; ++ } ++ if(menuItem._activeChangeId) { ++ menuItem.disconnect(menuItem._activeChangeId); ++ menuItem._activeChangeId = 0; ++ } ++ if(menuItem._sensitiveChangeId) { ++ menuItem.disconnect(menuItem._sensitiveChangeId); ++ menuItem._sensitiveChangeId = 0; ++ } ++ this.disconnect(menuItem._parentSensitiveChangeId); ++ if (menuItem == this._activeMenuItem) ++ this._activeMenuItem = null; ++ })); ++ ++ menuItem.actor.get_parent().remove_child(menuItem.actor); ++ if(menuItem instanceof PopupMenu.PopupSubMenuMenuItem) { ++ let newSubMenuMenuItem = new PopupMenu.PopupSubMenuMenuItem(labelText); ++ let appSubMenuItems = menuItem.menu._getMenuItems(); ++ for(let appSubMenuIdx in appSubMenuItems){ ++ let subMenuItem = appSubMenuItems[appSubMenuIdx]; ++ subMenuItem.actor.get_parent().remove_child(subMenuItem.actor); ++ newSubMenuMenuItem.menu.addMenuItem(subMenuItem); ++ } ++ this.addMenuItem(newSubMenuMenuItem, i); ++ } else ++ this.addMenuItem(menuItem, i); ++ } ++ ++ if(i > 0) { ++ let separator = new PopupMenu.PopupSeparatorMenuItem(); ++ this.addMenuItem(separator, i); ++ } ++ } ++ } ++ ++ // quit menu ++ let app = this._source.app; ++ let window = this._source.window; ++ let count = window ? 1 : getInterestingWindows(app).length; ++ if ( count > 0) { ++ this._appendSeparator(); ++ let quitFromTaskbarMenuText = ""; ++ if (count == 1) ++ quitFromTaskbarMenuText = _("Quit"); ++ else ++ quitFromTaskbarMenuText = _("Quit") + ' ' + count + ' ' + _("Windows"); ++ ++ this._quitfromTaskbarMenuItem = this._appendMenuItem(quitFromTaskbarMenuText); ++ this._quitfromTaskbarMenuItem.connect('activate', Lang.bind(this, function() { ++ let app = this._source.app; ++ let windows = window ? [window] : app.get_windows(); ++ for (i = 0; i < windows.length; i++) { ++ this._closeWindowInstance(windows[i]) ++ } ++ })); ++ } ++ } ++}); ++Signals.addSignalMethods(taskbarSecondaryMenu.prototype); ++adjustMenuRedisplay(taskbarSecondaryMenu.prototype); ++ ++/** ++ * This function is used for extendDashItemContainer ++ */ ++function ItemShowLabel() { ++ if (!this._labelText) ++ return; ++ ++ this.label.set_text(this._labelText); ++ this.label.opacity = 0; ++ this.label.show(); ++ ++ let [stageX, stageY] = this.get_transformed_position(); ++ let node = this.label.get_theme_node(); ++ ++ let itemWidth = this.allocation.x2 - this.allocation.x1; ++ let itemHeight = this.allocation.y2 - this.allocation.y1; ++ ++ let labelWidth = this.label.get_width(); ++ let labelHeight = this.label.get_height(); ++ ++ let position = this._dtpPanel.getPosition(); ++ let labelOffset = node.get_length('-x-offset'); ++ ++ // From TaskbarItemContainer ++ if (this._getIconAnimationOffset) ++ labelOffset += this._getIconAnimationOffset(); ++ ++ let xOffset = Math.floor((itemWidth - labelWidth) / 2); ++ let x = stageX + xOffset ++ let y = stageY + (itemHeight - labelHeight) * .5; ++ ++ switch(position) { ++ case St.Side.TOP: ++ y = stageY + labelOffset + itemHeight; ++ break; ++ case St.Side.BOTTOM: ++ y = stageY - labelHeight - labelOffset; ++ break; ++ case St.Side.LEFT: ++ x = stageX + labelOffset + itemWidth; ++ break; ++ case St.Side.RIGHT: ++ x = stageX - labelWidth - labelOffset; ++ break; ++ } ++ ++ // keep the label inside the screen border ++ // Only needed for the x coordinate. ++ ++ // Leave a few pixel gap ++ let gap = LABEL_GAP; ++ let monitor = Main.layoutManager.findMonitorForActor(this); ++ if ( x - monitor.x < gap) ++ x += monitor.x - x + labelOffset; ++ else if ( x + labelWidth > monitor.x + monitor.width - gap) ++ x -= x + labelWidth -( monitor.x + monitor.width) + gap; ++ ++ this.label.set_position(Math.round(x), Math.round(y)); ++ ++ let duration = Dash.DASH_ITEM_LABEL_SHOW_TIME; ++ ++ if (duration > 1) { ++ duration /= 1000; ++ } ++ ++ Utils.animate(this.label, { ++ opacity: 255, ++ time: duration, ++ transition: 'easeOutQuad', ++ }); ++}; ++ ++/** ++ * A wrapper class around the ShowAppsIcon class. ++ * ++ * - Pass settings to the constructor ++ * - set label position based on dash orientation (Note, I am reusing most machinery of the appIcon class) ++ * - implement a popupMenu based on the AppIcon code (Note, I am reusing most machinery of the appIcon class) ++ * ++ * I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973. ++ * thus use this pattern where the real showAppsIcon object is encaptulated, and a reference to it will be properly wired upon ++ * use of this class in place of the original showAppsButton. ++ * ++ */ ++var ShowAppsIconWrapper = Utils.defineClass({ ++ Name: 'DashToPanel.ShowAppsIconWrapper', ++ ++ _init: function(dtpPanel) { ++ this.realShowAppsIcon = new Dash.ShowAppsIcon(); ++ ++ Utils.wrapActor(this.realShowAppsIcon); ++ Utils.wrapActor(this.realShowAppsIcon.toggleButton); ++ ++ /* the variable equivalent to toggleButton has a different name in the appIcon class ++ (actor): duplicate reference to easily reuse appIcon methods */ ++ this.actor = this.realShowAppsIcon.toggleButton; ++ this.realShowAppsIcon.show(false); ++ ++ // Re-use appIcon methods ++ this._removeMenuTimeout = AppDisplay.AppIcon.prototype._removeMenuTimeout; ++ this._setPopupTimeout = AppDisplay.AppIcon.prototype._setPopupTimeout; ++ this._onKeyboardPopupMenu = AppDisplay.AppIcon.prototype._onKeyboardPopupMenu; ++ ++ // No action on clicked (showing of the appsview is controlled elsewhere) ++ this._onClicked = Lang.bind(this, function(actor, button) { ++ this._removeMenuTimeout(); ++ }); ++ ++ this.actor.connect('leave-event', Lang.bind(this, this._onLeaveEvent)); ++ this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); ++ this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent)); ++ this.actor.connect('clicked', Lang.bind(this, this._onClicked)); ++ this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu)); ++ ++ this._menu = null; ++ this._menuManager = new PopupMenu.PopupMenuManager(this.actor); ++ this._menuTimeoutId = 0; ++ ++ this.realShowAppsIcon._dtpPanel = dtpPanel; ++ Taskbar.extendDashItemContainer(this.realShowAppsIcon); ++ ++ let customIconPath = Me.settings.get_string('show-apps-icon-file'); ++ ++ this.realShowAppsIcon.icon.createIcon = function(size) { ++ this._iconActor = new St.Icon({ icon_name: 'view' + (Config.PACKAGE_VERSION < '3.20' ? '' : '-app') + '-grid-symbolic', ++ icon_size: size, ++ style_class: 'show-apps-icon', ++ track_hover: true }); ++ ++ if (customIconPath) { ++ this._iconActor.gicon = new Gio.FileIcon({ file: Gio.File.new_for_path(customIconPath) }); ++ } ++ ++ return this._iconActor; ++ }; ++ ++ this._changedShowAppsIconId = Me.settings.connect('changed::show-apps-icon-file', () => { ++ customIconPath = Me.settings.get_string('show-apps-icon-file'); ++ this.realShowAppsIcon.icon._createIconTexture(this.realShowAppsIcon.icon.iconSize); ++ }); ++ ++ this._changedAppIconPaddingId = Me.settings.connect('changed::appicon-padding', () => this.setShowAppsPadding()); ++ this._changedAppIconSidePaddingId = Me.settings.connect('changed::show-apps-icon-side-padding', () => this.setShowAppsPadding()); ++ ++ this.setShowAppsPadding(); ++ }, ++ ++ _onButtonPress: function(_actor, event) { ++ let button = event.get_button(); ++ if (button == 1) { ++ this._setPopupTimeout(); ++ } else if (button == 3) { ++ this.popupMenu(); ++ return Clutter.EVENT_STOP; ++ } ++ return Clutter.EVENT_PROPAGATE; ++ }, ++ ++ _onLeaveEvent: function(_actor, _event) { ++ this.actor.fake_release(); ++ this._removeMenuTimeout(); ++ }, ++ ++ _onTouchEvent: function(actor, event) { ++ if (event.type() == Clutter.EventType.TOUCH_BEGIN) ++ this._setPopupTimeout(); ++ ++ return Clutter.EVENT_PROPAGATE; ++ }, ++ ++ _onMenuPoppedDown: function() { ++ this._menu.sourceActor = this.actor; ++ this.actor.sync_hover(); ++ this.emit('menu-state-changed', false); ++ }, ++ ++ setShowAppsPadding: function() { ++ let padding = getIconPadding(this.realShowAppsIcon._dtpPanel.monitor.index); ++ let sidePadding = Me.settings.get_int('show-apps-icon-side-padding'); ++ let isVertical = this.realShowAppsIcon._dtpPanel.checkIfVertical(); ++ ++ this.actor.set_style('padding:' + (padding + (isVertical ? sidePadding : 0)) + 'px ' + (padding + (isVertical ? 0 : sidePadding)) + 'px;'); ++ }, ++ ++ createMenu: function() { ++ if (!this._menu) { ++ this._menu = new MyShowAppsIconMenu(this.actor, this.realShowAppsIcon._dtpPanel); ++ this._menu.connect('open-state-changed', Lang.bind(this, function(menu, isPoppedUp) { ++ if (!isPoppedUp) ++ this._onMenuPoppedDown(); ++ })); ++ let id = Main.overview.connect('hiding', Lang.bind(this, function() { ++ this._menu.close(); ++ })); ++ this._menu.actor.connect('destroy', function() { ++ Main.overview.disconnect(id); ++ }); ++ this._menuManager.addMenu(this._menu); ++ } ++ }, ++ ++ popupMenu: function() { ++ this._removeMenuTimeout(); ++ this.actor.fake_release(); ++ this.createMenu(this.actor); ++ ++ //this.emit('menu-state-changed', true); ++ ++ this.actor.set_hover(true); ++ this._menu.popup(); ++ this._menuManager.ignoreRelease(); ++ this.emit('sync-tooltip'); ++ ++ return false; ++ }, ++ ++ shouldShowTooltip: function() { ++ return Me.settings.get_boolean('show-tooltip') && ++ (this.actor.hover && (!this._menu || !this._menu.isOpen)); ++ }, ++ ++ destroy: function() { ++ Me.settings.disconnect(this._changedShowAppsIconId); ++ Me.settings.disconnect(this._changedAppIconSidePaddingId); ++ Me.settings.disconnect(this._changedAppIconPaddingId); ++ ++ this.realShowAppsIcon.destroy(); ++ } ++}); ++Signals.addSignalMethods(ShowAppsIconWrapper.prototype); ++ ++/** ++ * A menu for the showAppsIcon ++ */ ++var MyShowAppsIconMenu = Utils.defineClass({ ++ Name: 'DashToPanel.ShowAppsIconMenu', ++ Extends: taskbarSecondaryMenu, ++ ParentConstrParams: [[0], [1]], ++ ++ _dtpRedisplay: function() { ++ this.removeAll(); ++ ++ // Only add menu entries for commands that exist in path ++ function _appendItem(obj, info) { ++ if (Utils.checkIfCommandExists(info.cmd[0])) { ++ let item = obj._appendMenuItem(_(info.title)); ++ ++ item.connect('activate', function() { ++ Util.spawn(info.cmd); ++ }); ++ return item; ++ } ++ ++ return null; ++ } ++ ++ function _appendList(obj, commandList, titleList) { ++ if (commandList.length != titleList.length) { ++ return; ++ } ++ ++ for (var entry = 0; entry < commandList.length; entry++) { ++ _appendItem(obj, { ++ title: titleList[entry], ++ cmd: commandList[entry].split(' ') ++ }); ++ } ++ } ++ ++ if (this.sourceActor != Main.layoutManager.dummyCursor) { ++ _appendItem(this, { ++ title: 'Power options', ++ cmd: ['gnome-control-center', 'power'] ++ }); ++ ++ _appendItem(this, { ++ title: 'Event logs', ++ cmd: ['gnome-logs'] ++ }); ++ ++ _appendItem(this, { ++ title: 'System', ++ cmd: ['gnome-control-center', 'info-overview'] ++ }); ++ ++ _appendItem(this, { ++ title: 'Device Management', ++ cmd: ['gnome-control-center', 'display'] ++ }); ++ ++ _appendItem(this, { ++ title: 'Disk Management', ++ cmd: ['gnome-disks'] ++ }); ++ ++ _appendList( ++ this, ++ Me.settings.get_strv('show-apps-button-context-menu-commands'), ++ Me.settings.get_strv('show-apps-button-context-menu-titles') ++ ) ++ ++ this._appendSeparator(); ++ } ++ ++ _appendItem(this, { ++ title: 'Terminal', ++ cmd: ['gnome-terminal'] ++ }); ++ ++ _appendItem(this, { ++ title: 'System monitor', ++ cmd: ['gnome-system-monitor'] ++ }); ++ ++ _appendItem(this, { ++ title: 'Files', ++ cmd: ['nautilus'] ++ }); ++ ++ _appendItem(this, { ++ title: 'Extensions', ++ cmd: ['gnome-shell-extension-prefs'] ++ }); ++ ++ _appendItem(this, { ++ title: 'Settings', ++ cmd: ['gnome-control-center', 'wifi'] ++ }); ++ ++ _appendList( ++ this, ++ Me.settings.get_strv('panel-context-menu-commands'), ++ Me.settings.get_strv('panel-context-menu-titles') ++ ) ++ ++ this._appendSeparator(); ++ ++ let lockTaskbarMenuItem = this._appendMenuItem(Me.settings.get_boolean('taskbar-locked') ? _('Unlock taskbar') : _('Lock taskbar')); ++ lockTaskbarMenuItem.connect('activate', () => { ++ Me.settings.set_boolean('taskbar-locked', !Me.settings.get_boolean('taskbar-locked')); ++ }); ++ ++ let settingsMenuItem = this._appendMenuItem(_('Dash to Panel Settings')); ++ settingsMenuItem.connect('activate', function () { ++ let command = ["gnome-shell-extension-prefs"]; ++ ++ if (Config.PACKAGE_VERSION > '3.36') { ++ command = ["gnome-extensions", "prefs"]; ++ } ++ ++ Util.spawn(command.concat([Me.metadata.uuid])); ++ }); ++ ++ if(this._source._dtpPanel) { ++ this._appendSeparator(); ++ let item = this._appendMenuItem(this._source._dtpPanel._restoreWindowList ? _('Restore Windows') : _('Show Desktop')); ++ item.connect('activate', Lang.bind(this._source._dtpPanel, this._source._dtpPanel._onShowDesktopButtonPress)); ++ } ++ } ++}); ++adjustMenuRedisplay(MyShowAppsIconMenu.prototype); ++ ++function adjustMenuRedisplay(menuProto) { ++ menuProto[menuRedisplayFunc] = function() { this._dtpRedisplay(menuRedisplayFunc) }; ++} ++ ++var getIconContainerStyle = function(isVertical) { ++ let style = 'padding: '; ++ ++ if (Me.settings.get_boolean('group-apps')) { ++ style += (isVertical ? '0;' : '0 ' + DEFAULT_PADDING_SIZE + 'px;'); ++ } else { ++ style += (isVertical ? '' : '0 ') + DEFAULT_PADDING_SIZE + 'px;'; ++ } ++ ++ return style; ++} +diff --git a/extensions/dash-to-panel/convenience.js b/extensions/dash-to-panel/convenience.js +new file mode 100644 +index 00000000..57d2f136 +--- /dev/null ++++ b/extensions/dash-to-panel/convenience.js +@@ -0,0 +1,89 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++const Config = imports.misc.config; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Gettext = imports.gettext; ++const Gio = imports.gi.Gio; ++ ++/** ++ * initTranslations: ++ * @domain: (optional): the gettext domain to use ++ * ++ * Initialize Gettext to load translations from extensionsdir/locale. ++ * If @domain is not provided, it will be taken from metadata['gettext-domain'] ++ */ ++function initTranslations(domain) { ++ let extension = ExtensionUtils.getCurrentExtension(); ++ ++ domain = domain || extension.metadata['gettext-domain']; ++ ++ // Check if this extension was built with "make zip-file", and thus ++ // has the locale files in a subfolder ++ // otherwise assume that extension has been installed in the ++ // same prefix as gnome-shell ++ let localeDir = extension.dir.get_child('locale'); ++ if (localeDir.query_exists(null)) ++ Gettext.bindtextdomain(domain, localeDir.get_path()); ++ else ++ Gettext.bindtextdomain(domain, Config.LOCALEDIR); ++} ++ ++/** ++ * getSettings: ++ * @schema: (optional): the GSettings schema id ++ * ++ * Builds and return a GSettings schema for @schema, using schema files ++ * in extensionsdir/schemas. If @schema is not provided, it is taken from ++ * metadata['settings-schema']. ++ */ ++function getSettings(schema) { ++ let extension = ExtensionUtils.getCurrentExtension(); ++ ++ schema = schema || extension.metadata['settings-schema']; ++ ++ const GioSSS = Gio.SettingsSchemaSource; ++ ++ // Check if this extension was built with "make zip-file", and thus ++ // has the schema files in a subfolder ++ // otherwise assume that extension has been installed in the ++ // same prefix as gnome-shell (and therefore schemas are available ++ // in the standard folders) ++ let schemaDir = extension.dir.get_child('schemas'); ++ let schemaSource; ++ if (schemaDir.query_exists(null)) ++ schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), ++ GioSSS.get_default(), ++ false); ++ else ++ schemaSource = GioSSS.get_default(); ++ ++ let schemaObj = schemaSource.lookup(schema, true); ++ if (!schemaObj) ++ throw new Error('Schema ' + schema + ' could not be found for extension ' ++ + extension.metadata.uuid + '. Please check your installation.'); ++ ++ return new Gio.Settings({ ++ settings_schema: schemaObj ++ }); ++} +\ No newline at end of file +diff --git a/extensions/dash-to-panel/extension.js b/extensions/dash-to-panel/extension.js +new file mode 100644 +index 00000000..8ab108f2 +--- /dev/null ++++ b/extensions/dash-to-panel/extension.js +@@ -0,0 +1,144 @@ ++/* ++ * Dash-To-Panel extension for Gnome 3 ++ * Copyright 2016 Jason DeRose (jderose9) and Charles Gagnon (charlesg99) ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++ ++ ++const Main = imports.ui.main; ++const Meta = imports.gi.Meta; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Lang = imports.lang; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const WindowManager = imports.ui.windowManager; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Mainloop = imports.mainloop; ++const Signals = imports.signals; ++ ++const Me = ExtensionUtils.getCurrentExtension(); ++const Convenience = Me.imports.convenience; ++const PanelManager = Me.imports.panelManager; ++const Utils = Me.imports.utils; ++ ++const UBUNTU_DOCK_UUID = 'ubuntu-dock@ubuntu.com'; ++ ++let panelManager; ++let oldDash; ++let extensionChangedHandler; ++let disabledUbuntuDock; ++let extensionSystem = (Main.extensionManager || imports.ui.extensionSystem); ++ ++function init() { ++ Convenience.initTranslations(Utils.TRANSLATION_DOMAIN); ++ ++ //create an object that persists until gnome-shell is restarted, even if the extension is disabled ++ Me.persistentStorage = {}; ++} ++ ++function enable() { ++ // The Ubuntu Dock extension might get enabled after this extension ++ extensionChangedHandler = extensionSystem.connect('extension-state-changed', (data, extension) => { ++ if (extension.uuid === UBUNTU_DOCK_UUID && extension.state === 1) { ++ _enable(); ++ } ++ }); ++ ++ //create a global object that can emit signals and conveniently expose functionalities to other extensions ++ global.dashToPanel = {}; ++ Signals.addSignalMethods(global.dashToPanel); ++ ++ _enable(); ++} ++ ++function _enable() { ++ let ubuntuDock = Main.extensionManager ? ++ Main.extensionManager.lookup(UBUNTU_DOCK_UUID) : //gnome-shell >= 3.33.4 ++ ExtensionUtils.extensions[UBUNTU_DOCK_UUID]; ++ ++ if (ubuntuDock && ubuntuDock.stateObj && ubuntuDock.stateObj.dockManager) { ++ // Disable Ubuntu Dock ++ let extensionOrder = (extensionSystem.extensionOrder || extensionSystem._extensionOrder); ++ ++ Utils.getStageTheme().get_theme().unload_stylesheet(ubuntuDock.stylesheet); ++ ubuntuDock.stateObj.disable(); ++ disabledUbuntuDock = true; ++ ubuntuDock.state = 2; //ExtensionState.DISABLED ++ extensionOrder.splice(extensionOrder.indexOf(UBUNTU_DOCK_UUID), 1); ++ ++ //reset to prevent conflicts with the ubuntu-dock ++ if (panelManager) { ++ disable(true); ++ } ++ } ++ ++ if (panelManager) return; //already initialized ++ ++ Me.settings = Convenience.getSettings('org.gnome.shell.extensions.dash-to-panel'); ++ Me.desktopSettings = Convenience.getSettings('org.gnome.desktop.interface'); ++ ++ panelManager = new PanelManager.dtpPanelManager(); ++ ++ panelManager.enable(); ++ ++ Utils.removeKeybinding('open-application-menu'); ++ Utils.addKeybinding( ++ 'open-application-menu', ++ new Gio.Settings({ schema_id: WindowManager.SHELL_KEYBINDINGS_SCHEMA }), ++ Lang.bind(this, function() { ++ if(Me.settings.get_boolean('show-appmenu')) ++ Main.wm._toggleAppMenu(); ++ else ++ panelManager.primaryPanel.taskbar.popupFocusedAppSecondaryMenu(); ++ }), ++ Shell.ActionMode.NORMAL | Shell.ActionMode.POPUP ++ ); ++ ++ // Pretend I'm the dash: meant to make appgrd swarm animation come from the ++ // right position of the appShowButton. ++ oldDash = Main.overview._dash; ++ Main.overview._dash = panelManager.primaryPanel.taskbar; ++} ++ ++function disable(reset) { ++ panelManager.disable(); ++ Main.overview._dash = oldDash; ++ Me.settings.run_dispose(); ++ Me.desktopSettings.run_dispose(); ++ ++ delete Me.settings; ++ oldDash = null; ++ panelManager = null; ++ ++ Utils.removeKeybinding('open-application-menu'); ++ Utils.addKeybinding( ++ 'open-application-menu', ++ new Gio.Settings({ schema_id: WindowManager.SHELL_KEYBINDINGS_SCHEMA }), ++ Lang.bind(Main.wm, Main.wm._toggleAppMenu), ++ Shell.ActionMode.NORMAL | Shell.ActionMode.POPUP ++ ); ++ ++ if (!reset) { ++ extensionSystem.disconnect(extensionChangedHandler); ++ delete global.dashToPanel; ++ ++ // Re-enable Ubuntu Dock if it was disabled by dash to panel ++ if (disabledUbuntuDock && Main.sessionMode.allowExtensions) { ++ (extensionSystem._callExtensionEnable || extensionSystem.enableExtension).call(extensionSystem, UBUNTU_DOCK_UUID); ++ } ++ } ++} +\ No newline at end of file +diff --git a/extensions/dash-to-panel/img/highlight_stacked_bg.svg b/extensions/dash-to-panel/img/highlight_stacked_bg.svg +new file mode 100644 +index 00000000..977146b1 +--- /dev/null ++++ b/extensions/dash-to-panel/img/highlight_stacked_bg.svg +@@ -0,0 +1,7 @@ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-panel/img/highlight_stacked_bg_2.svg b/extensions/dash-to-panel/img/highlight_stacked_bg_2.svg +new file mode 100644 +index 00000000..47aa8025 +--- /dev/null ++++ b/extensions/dash-to-panel/img/highlight_stacked_bg_2.svg +@@ -0,0 +1,7 @@ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-panel/img/highlight_stacked_bg_3.svg b/extensions/dash-to-panel/img/highlight_stacked_bg_3.svg +new file mode 100644 +index 00000000..80420fdb +--- /dev/null ++++ b/extensions/dash-to-panel/img/highlight_stacked_bg_3.svg +@@ -0,0 +1,7 @@ ++ ++ ++ ++ ++ ++ ++ +diff --git a/extensions/dash-to-panel/intellihide.js b/extensions/dash-to-panel/intellihide.js +new file mode 100644 +index 00000000..8fb1e976 +--- /dev/null ++++ b/extensions/dash-to-panel/intellihide.js +@@ -0,0 +1,401 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Lang = imports.lang; ++const Clutter = imports.gi.Clutter; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++ ++var GrabHelper = imports.ui.grabHelper; ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++const OverviewControls = imports.ui.overviewControls; ++const PointerWatcher = imports.ui.pointerWatcher; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Panel = Me.imports.panel; ++const Proximity = Me.imports.proximity; ++const Utils = Me.imports.utils; ++ ++//timeout intervals ++const CHECK_POINTER_MS = 200; ++const CHECK_GRAB_MS = 400; ++const POST_ANIMATE_MS = 50; ++const MIN_UPDATE_MS = 250; ++ ++//timeout names ++const T1 = 'checkGrabTimeout'; ++const T2 = 'limitUpdateTimeout'; ++const T3 = 'postAnimateTimeout'; ++const T4 = 'panelBoxClipTimeout'; ++ ++var SIDE_CONTROLS_ANIMATION_TIME = OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / (OverviewControls.SIDE_CONTROLS_ANIMATION_TIME > 1 ? 1000 : 1); ++ ++var Hold = { ++ NONE: 0, ++ TEMPORARY: 1, ++ PERMANENT: 2 ++}; ++ ++var Intellihide = Utils.defineClass({ ++ Name: 'DashToPanel.Intellihide', ++ ++ _init: function(dtpPanel) { ++ this._dtpPanel = dtpPanel; ++ this._panelBox = dtpPanel.panelBox; ++ this._panelManager = dtpPanel.panelManager; ++ this._proximityManager = this._panelManager.proximityManager; ++ this._holdStatus = Hold.NONE; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._timeoutsHandler = new Utils.TimeoutsHandler(); ++ ++ this._intellihideChangedId = Me.settings.connect('changed::intellihide', () => this._changeEnabledStatus()); ++ this._intellihideOnlySecondaryChangedId = Me.settings.connect('changed::intellihide-only-secondary', () => this._changeEnabledStatus()); ++ ++ this.enabled = false; ++ this._changeEnabledStatus(); ++ }, ++ ++ enable: function() { ++ this.enabled = true; ++ this._monitor = this._dtpPanel.monitor; ++ this._animationDestination = -1; ++ this._pendingUpdate = false; ++ this._hoveredOut = false; ++ this._windowOverlap = false; ++ this._translationProp = 'translation_' + (this._dtpPanel.checkIfVertical() ? 'x' : 'y'); ++ ++ this._panelBox.translation_y = 0; ++ this._panelBox.translation_x = 0; ++ ++ this._setTrackPanel(true); ++ this._bindGeneralSignals(); ++ ++ if (Me.settings.get_boolean('intellihide-hide-from-windows')) { ++ this._proximityWatchId = this._proximityManager.createWatch( ++ this._panelBox.get_parent(), ++ Proximity.Mode[Me.settings.get_string('intellihide-behaviour')], ++ 0, 0, ++ overlap => { ++ this._windowOverlap = overlap; ++ this._queueUpdatePanelPosition(); ++ } ++ ); ++ } ++ ++ this._setRevealMechanism(); ++ this._queueUpdatePanelPosition(); ++ }, ++ ++ disable: function(reset) { ++ if (this._proximityWatchId) { ++ this._proximityManager.removeWatch(this._proximityWatchId); ++ } ++ ++ this._setTrackPanel(false); ++ ++ this._signalsHandler.destroy(); ++ this._timeoutsHandler.destroy(); ++ ++ this._removeRevealMechanism(); ++ ++ this._revealPanel(!reset); ++ ++ this.enabled = false; ++ }, ++ ++ destroy: function() { ++ Me.settings.disconnect(this._intellihideChangedId); ++ Me.settings.disconnect(this._intellihideOnlySecondaryChangedId); ++ ++ if (this.enabled) { ++ this.disable(); ++ } ++ }, ++ ++ toggle: function() { ++ this[this._holdStatus & Hold.PERMANENT ? 'release' : 'revealAndHold'](Hold.PERMANENT); ++ }, ++ ++ revealAndHold: function(holdStatus) { ++ if (this.enabled && !this._holdStatus) { ++ this._revealPanel(); ++ } ++ ++ this._holdStatus |= holdStatus; ++ }, ++ ++ release: function(holdStatus) { ++ this._holdStatus -= holdStatus; ++ ++ if (this.enabled && !this._holdStatus) { ++ this._queueUpdatePanelPosition(); ++ } ++ }, ++ ++ reset: function() { ++ this.disable(true); ++ this.enable(); ++ }, ++ ++ _changeEnabledStatus: function() { ++ let intellihide = Me.settings.get_boolean('intellihide'); ++ let onlySecondary = Me.settings.get_boolean('intellihide-only-secondary'); ++ let enabled = intellihide && !(this._dtpPanel.isPrimary && onlySecondary); ++ ++ if (this.enabled !== enabled) { ++ this[enabled ? 'enable' : 'disable'](); ++ } ++ }, ++ ++ _bindGeneralSignals: function() { ++ this._signalsHandler.add( ++ [ ++ this._dtpPanel.taskbar, ++ 'menu-closed', ++ () => this._panelBox.sync_hover() ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::intellihide-use-pressure', ++ 'changed::intellihide-hide-from-windows', ++ 'changed::intellihide-behaviour', ++ 'changed::intellihide-pressure-threshold', ++ 'changed::intellihide-pressure-time' ++ ], ++ () => this.reset() ++ ], ++ [ ++ this._panelBox, ++ 'notify::hover', ++ () => this._onHoverChanged() ++ ], ++ [ ++ this._dtpPanel.taskbar.previewMenu, ++ 'open-state-changed', ++ () => this._queueUpdatePanelPosition() ++ ], ++ [ ++ Main.overview, ++ [ ++ 'showing', ++ 'hiding' ++ ], ++ () => this._queueUpdatePanelPosition() ++ ] ++ ); ++ }, ++ ++ _onHoverChanged: function() { ++ this._hoveredOut = !this._panelBox.hover; ++ this._queueUpdatePanelPosition(); ++ }, ++ ++ _setTrackPanel: function(enable) { ++ let trackedIndex = Main.layoutManager._findActor(this._panelBox); ++ let actorData = Main.layoutManager._trackedActors[trackedIndex] ++ ++ actorData.affectsStruts = !enable; ++ actorData.trackFullscreen = !enable; ++ ++ this._panelBox.track_hover = enable; ++ this._panelBox.reactive = enable; ++ this._panelBox.visible = enable ? enable : this._panelBox.visible; ++ ++ Main.layoutManager._queueUpdateRegions(); ++ }, ++ ++ _setRevealMechanism: function() { ++ if (global.display.supports_extended_barriers() && Me.settings.get_boolean('intellihide-use-pressure')) { ++ this._edgeBarrier = this._createBarrier(); ++ this._pressureBarrier = new Layout.PressureBarrier( ++ Me.settings.get_int('intellihide-pressure-threshold'), ++ Me.settings.get_int('intellihide-pressure-time'), ++ Shell.ActionMode.NORMAL ++ ); ++ this._pressureBarrier.addBarrier(this._edgeBarrier); ++ this._signalsHandler.add([this._pressureBarrier, 'trigger', () => this._queueUpdatePanelPosition(true)]); ++ } else { ++ this._pointerWatch = PointerWatcher.getPointerWatcher() ++ .addWatch(CHECK_POINTER_MS, (x, y) => this._checkMousePointer(x, y)); ++ } ++ }, ++ ++ _removeRevealMechanism: function() { ++ if (this._pointerWatch) { ++ PointerWatcher.getPointerWatcher()._removeWatch(this._pointerWatch); ++ } ++ ++ if (this._pressureBarrier) { ++ this._pressureBarrier.destroy(); ++ this._edgeBarrier.destroy(); ++ } ++ }, ++ ++ _createBarrier: function() { ++ let position = this._dtpPanel.geom.position; ++ let opts = { display: global.display }; ++ ++ if (this._dtpPanel.checkIfVertical()) { ++ opts.y1 = this._monitor.y; ++ opts.y2 = this._monitor.y + this._monitor.height; ++ opts.x1 = opts.x2 = this._monitor.x; ++ } else { ++ opts.x1 = this._monitor.x; ++ opts.x2 = this._monitor.x + this._monitor.width; ++ opts.y1 = opts.y2 = this._monitor.y; ++ } ++ ++ if (position == St.Side.TOP) { ++ opts.directions = Meta.BarrierDirection.POSITIVE_Y; ++ } else if (position == St.Side.BOTTOM) { ++ opts.y1 = opts.y2 = opts.y1 + this._monitor.height; ++ opts.directions = Meta.BarrierDirection.NEGATIVE_Y; ++ } else if (position == St.Side.LEFT) { ++ opts.directions = Meta.BarrierDirection.POSITIVE_X; ++ } else { ++ opts.x1 = opts.x2 = opts.x1 + this._monitor.width; ++ opts.directions = Meta.BarrierDirection.NEGATIVE_X; ++ } ++ ++ return new Meta.Barrier(opts); ++ }, ++ ++ _checkMousePointer: function(x, y) { ++ let position = this._dtpPanel.geom.position; ++ ++ if (!this._panelBox.hover && !Main.overview.visible && ++ ((position == St.Side.TOP && y <= this._monitor.y + 1) || ++ (position == St.Side.BOTTOM && y >= this._monitor.y + this._monitor.height - 1) || ++ (position == St.Side.LEFT && x <= this._monitor.x + 1) || ++ (position == St.Side.RIGHT && x >= this._monitor.x + this._monitor.width - 1)) && ++ ((x >= this._monitor.x && x < this._monitor.x + this._monitor.width) && ++ (y >= this._monitor.y && y < this._monitor.y + this._monitor.height))) { ++ this._queueUpdatePanelPosition(true); ++ } ++ }, ++ ++ _queueUpdatePanelPosition: function(fromRevealMechanism) { ++ if (!fromRevealMechanism && this._timeoutsHandler.getId(T2) && !Main.overview.visible) { ++ //unless this is a mouse interaction or entering/leaving the overview, limit the number ++ //of updates, but remember to update again when the limit timeout is reached ++ this._pendingUpdate = true; ++ } else if (!this._holdStatus) { ++ this._checkIfShouldBeVisible(fromRevealMechanism) ? this._revealPanel() : this._hidePanel(); ++ this._timeoutsHandler.add([T2, MIN_UPDATE_MS, () => this._endLimitUpdate()]); ++ } ++ }, ++ ++ _endLimitUpdate: function() { ++ if (this._pendingUpdate) { ++ this._pendingUpdate = false; ++ this._queueUpdatePanelPosition(); ++ } ++ }, ++ ++ _checkIfShouldBeVisible: function(fromRevealMechanism) { ++ if (Main.overview.visibleTarget || this._dtpPanel.taskbar.previewMenu.opened || ++ this._panelBox.get_hover() || this._checkIfGrab()) { ++ return true; ++ } ++ ++ if (fromRevealMechanism) { ++ let mouseBtnIsPressed = global.get_pointer()[2] & Clutter.ModifierType.BUTTON1_MASK; ++ ++ //the user is trying to reveal the panel ++ if (this._monitor.inFullscreen && !mouseBtnIsPressed) { ++ return Me.settings.get_boolean('intellihide-show-in-fullscreen'); ++ } ++ ++ return !mouseBtnIsPressed; ++ } ++ ++ if (!Me.settings.get_boolean('intellihide-hide-from-windows')) { ++ return this._panelBox.hover; ++ } ++ ++ return !this._windowOverlap; ++ }, ++ ++ _checkIfGrab: function() { ++ if (GrabHelper._grabHelperStack.some(gh => gh._owner == this._dtpPanel.panel.actor)) { ++ //there currently is a grab on a child of the panel, check again soon to catch its release ++ this._timeoutsHandler.add([T1, CHECK_GRAB_MS, () => this._queueUpdatePanelPosition()]); ++ ++ return true; ++ } ++ }, ++ ++ _revealPanel: function(immediate) { ++ if (!this._panelBox.visible) { ++ this._panelBox.visible = true; ++ this._dtpPanel.taskbar._shownInitially = false; ++ } ++ ++ this._animatePanel(0, immediate); ++ }, ++ ++ _hidePanel: function(immediate) { ++ let position = this._dtpPanel.geom.position; ++ let size = this._panelBox[position == St.Side.LEFT || position == St.Side.RIGHT ? 'width' : 'height']; ++ let coefficient = position == St.Side.TOP || position == St.Side.LEFT ? -1 : 1; ++ ++ this._animatePanel(size * coefficient, immediate); ++ }, ++ ++ _animatePanel: function(destination, immediate) { ++ let animating = Utils.isAnimating(this._panelBox, this._translationProp); ++ ++ if (!((animating && destination === this._animationDestination) || ++ (!animating && destination === this._panelBox[this._translationProp]))) { ++ //the panel isn't already at, or animating to the asked destination ++ if (animating) { ++ Utils.stopAnimations(this._panelBox); ++ } ++ ++ this._animationDestination = destination; ++ ++ if (immediate) { ++ this._panelBox[this._translationProp] = destination; ++ this._panelBox.visible = !destination; ++ } else { ++ let tweenOpts = { ++ //when entering/leaving the overview, use its animation time instead of the one from the settings ++ time: Main.overview.visible ? ++ SIDE_CONTROLS_ANIMATION_TIME : ++ Me.settings.get_int('intellihide-animation-time') * 0.001, ++ //only delay the animation when hiding the panel after the user hovered out ++ delay: destination != 0 && this._hoveredOut ? Me.settings.get_int('intellihide-close-delay') * 0.001 : 0, ++ transition: 'easeOutQuad', ++ onComplete: () => { ++ this._panelBox.visible = !destination; ++ Main.layoutManager._queueUpdateRegions(); ++ this._timeoutsHandler.add([T3, POST_ANIMATE_MS, () => this._queueUpdatePanelPosition()]); ++ } ++ }; ++ ++ tweenOpts[this._translationProp] = destination; ++ Utils.animate(this._panelBox, tweenOpts); ++ } ++ } ++ ++ this._hoveredOut = false; ++ }, ++}); +\ No newline at end of file +diff --git a/extensions/dash-to-panel/meson.build b/extensions/dash-to-panel/meson.build +new file mode 100644 +index 00000000..70680479 +--- /dev/null ++++ b/extensions/dash-to-panel/meson.build +@@ -0,0 +1,34 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_sources += files( ++ 'appIcons.js', ++ 'convenience.js', ++ 'extension.js', ++ 'intellihide.js', ++ 'overview.js', ++ 'panel.js', ++ 'panelManager.js', ++ 'panelPositions.js', ++ 'panelSettings.js', ++ 'panelStyle.js', ++ 'prefs.js', ++ 'progress.js', ++ 'proximity.js', ++ 'Settings.ui', ++ 'taskbar.js', ++ 'transparency.js', ++ 'utils.js', ++ 'windowPreview.js' ++) ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') ++ ++img_data = files( ++ 'img/highlight_stacked_bg_2.svg', ++ 'img/highlight_stacked_bg_3.svg', ++ 'img/highlight_stacked_bg.svg' ++) ++install_data(img_data, install_dir: join_paths(extensiondir, uuid, 'img')) +diff --git a/extensions/dash-to-panel/metadata.json.in b/extensions/dash-to-panel/metadata.json.in +new file mode 100644 +index 00000000..5c7eab09 +--- /dev/null ++++ b/extensions/dash-to-panel/metadata.json.in +@@ -0,0 +1,12 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"original-author": "charlesg99", ++"name": "Dash to Panel", ++"description": "An icon taskbar for the Gnome Shell. This extension moves the dash into the gnome main panel so that the application launchers and system tray are combined into a single panel, similar to that found in KDE Plasma and Windows 7+. A separate dock is no longer needed for easy access to running and favorited applications.\n\nFor a more traditional experience, you may also want to use Tweak Tool to enable Windows > Titlebar Buttons > Minimize & Maximize.\n\nFor the best support, please report any issues on Github. Dash-to-panel is developed and maintained by @jderose9 and @charlesg99.", ++"shell-version": [ "@shell_current@" ], ++"url": "https://github.com/jderose9/dash-to-panel", ++"version": 42 ++} +diff --git a/extensions/dash-to-panel/org.gnome.shell.extensions.dash-to-panel.gschema.xml b/extensions/dash-to-panel/org.gnome.shell.extensions.dash-to-panel.gschema.xml +new file mode 100644 +index 00000000..2c9e86a5 +--- /dev/null ++++ b/extensions/dash-to-panel/org.gnome.shell.extensions.dash-to-panel.gschema.xml +@@ -0,0 +1,1278 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ 'BOTTOM' ++ Panel position (Deprecated) ++ Panel is shown on the Bottom or Top of the screen. ++ ++ ++ true ++ Sync element positions ++ Sync panel element positions on all monitors. ++ ++ ++ '{}' ++ Panel positions ++ Panel positions (JSON). ++ ++ ++ '{}' ++ Panel element positions ++ Panel element positions (JSON). ++ ++ ++ '{}' ++ Percentages of screen edge for panel to span ++ Length of the panels, in percent (JSON). ++ ++ ++ '{}' ++ Positions along screen edge ++ Where to show the panels if it is not the full length of the screen edge (JSON). ++ ++ ++ '{}' ++ Panel sizes ++ Sizes of panels, in pixels. ++ ++ ++ 48 ++ Panel size (Deprecated) ++ Set the size of the panel. ++ ++ ++ false ++ Override Show Desktop line color ++ Replace current Show Desktop button line color ++ ++ ++ "rgba(200,200,200,0.2)" ++ Custom Show Desktop line color ++ Custom Show Desktop button line color ++ ++ ++ 'BOTTOM' ++ Dot position ++ Running indicators are shown on the Bottom or Top of the screen. ++ ++ ++ 'METRO' ++ Style of the running indicator (focused) ++ Style of the running indicator for the icon for the currently focused application ++ ++ ++ 'METRO' ++ Style of the running indicator (unfocused) ++ Style of the running indicator for the icon for applications which are not currently focused ++ ++ ++ false ++ Running indicator dominant color ++ Whether to use the app icon's dominant color for .app-well-running-dot ++ ++ ++ false ++ Running indicator color override ++ Whether to override the theme background color for .app-well-running-dot ++ ++ ++ "#5294e2" ++ Color of running indicator (1 window) ++ Customize the color of the running indicator when one window is running for that application ++ ++ ++ "#5294e2" ++ Color of running indicator (2 windows) ++ Customize the color of the running indicator when two windows are running for that application ++ ++ ++ "#5294e2" ++ Color of running indicator (3 windows) ++ Customize the color of the running indicator when three windows are running for that application ++ ++ ++ "#5294e2" ++ Color of running indicator (4+ windows) ++ Customize the color of the running indicator when four or more windows are running for that application ++ ++ ++ false ++ Unfocused color is different than focused ++ Whether to apply a 2nd color scheme to the indicator when the app is not focused ++ ++ ++ "#5294e2" ++ Color of unfocused running indicator (1 window) ++ Customize the color of the unfocused running indicator when one window is running for that application ++ ++ ++ "#5294e2" ++ Color of unfocused running indicator (2 windows) ++ Customize the color of the unfocused running indicator when two windows are running for that application ++ ++ ++ "#5294e2" ++ Color of unfocused running indicator (3 windows) ++ Customize the color of the unfocused running indicator when three windows are running for that application ++ ++ ++ "#5294e2" ++ Color of unfocused running indicator (4+ windows) ++ Customize the color of the unfocused running indicator when four or more windows are running for that application ++ ++ ++ 3 ++ Running indicator height ++ Height of the running indicator line/diameter of window indicator dots ++ ++ ++ true ++ Highlight icon of focused application ++ Whether to highlight the background of the currently focused application's icon ++ ++ ++ false ++ Highlight icon dominant color ++ Base the active window highlight color on that application's icon ++ ++ ++ "#EEEEEE" ++ Color of highlight of focused application ++ Customize the color of the highlight of the focused application ++ ++ ++ 25 ++ Opacity of highlight of focused application ++ Customize the opacity of the highlight of the focused application ++ ++ ++ false ++ Keep dash ++ Whether to keep the stock gnome-shell dash while in overview ++ ++ ++ false ++ Keep top panel ++ Whether to keep the stock gnome-shell top panel ++ ++ ++ false ++ Panel menu buttons require click ++ Whether to activate the panel menu buttons on hover or on click ++ ++ ++ false ++ Force hot corner ++ Wheter to force having an Activities hot corner on the primary monitor ++ ++ ++ false ++ Lock the taskbar ++ Specifies if the user can modify the taskbar ++ ++ ++ false ++ Override theme background color ++ Replace current theme background color for the panel ++ ++ ++ "#000" ++ Custom background color ++ Custom background color for the panel ++ ++ ++ false ++ Custom background color ++ Replace current theme background color for the panel ++ ++ ++ false ++ Dynamic opacity ++ Enable dynamic opacity ++ ++ ++ 0.4 ++ Panel opacity ++ Custom opacity for the panel ++ ++ ++ 'ALL_WINDOWS' ++ Dynamic opacity behavior ++ Dictates which window type affects the panel opacity ++ ++ ++ 20 ++ Distance to change opacity ++ The distance a window needs to be from the panel to change opacity ++ ++ ++ 0.8 ++ Modified panel opacity ++ Modified opacity for the panel when a window is near ++ ++ ++ 300 ++ Opacity change duration ++ The duration of the animation when the opacity changes ++ ++ ++ false ++ Custom gradient ++ Replace current theme gradient for the panel ++ ++ ++ "#000" ++ Custom gradient top color ++ Custom gradient top color for the panel ++ ++ ++ 0 ++ Custom gradient top opacity ++ Custom gradient top opacity for the panel ++ ++ ++ "#000" ++ Custom gradient bottom color ++ Custom gradient bottom color for the panel ++ ++ ++ 0.2 ++ Custom gradient bottom opacity ++ Custom gradient bottom opacity for the panel ++ ++ ++ false ++ Intellihide ++ Whether to intelligently hide the panel ++ ++ ++ false ++ Only hide from windows ++ Dictates if the dash should only hide when in conflict with windows ++ ++ ++ 'FOCUSED_WINDOWS' ++ Intellihide behaviour ++ Dictates how to intelligently hide the panel ++ ++ ++ false ++ Intellihide pressure ++ To reveal the panel, pressure needs to be applied to the edege of the screen ++ ++ ++ 100 ++ Intellihide pressure threshold ++ The pressure needed to reveal the panel ++ ++ ++ 1000 ++ Intellihide pressure time ++ The numer of milliseconds that the pressure needs to be applied to reveal the panel ++ ++ ++ false ++ Intellihide pressure ++ Allow the panel to be revealed while an application is in fullscreen mode ++ ++ ++ false ++ Intellihide only secondary ++ Whether to only hide secondary panels ++ ++ ++ 200 ++ Intellihide animation time ++ The animation time (ms) to hide and reveal the panel ++ ++ ++ 400 ++ Intellihide close delay ++ The delay (ms) before hiding the panel ++ ++ ++ "<Super>i" ++ Keybinding toggle intellihide ++ Keybinding to reveal the panel while in intellihide mode ++ ++ ++ i']]]> ++ Keybinding toggle intellihide ++ Keybinding to reveal the panel while in intellihide mode ++ ++ ++ 2000 ++ Intellihide enable start delay ++ The delay before enabling intellihide on start ++ ++ ++ "" ++ Custom Show Applications icon ++ Customize the Show Applications icon ++ ++ ++ 8 ++ Show Applications icon side padding ++ Customize the Show Applications icon side padding ++ ++ ++ true ++ Override escape key ++ Override the escape key to return to the desktop when entering the overview using the Show Applications button ++ ++ ++ true ++ Animate Show Applications from the desktop ++ Animate Show Applications from the desktop ++ ++ ++ [] ++ Show Apps button context menu commands ++ Commands to add to the Show Apps button right click menu ++ ++ ++ [] ++ Show Apps button context menu titles ++ Titles for commands added to Show Apps button right click menu ++ ++ ++ [] ++ Panel context menu commands ++ Commands to add to the panel right click menu ++ ++ ++ [] ++ Panel context menu titles ++ Titles for commands added to panel right click menu ++ ++ ++ false ++ Show activities button ++ Show activities button on the left hand side of the taskbar ++ ++ ++ 8 ++ Width of show Desktop button ++ Customize the width of the show Desktop button ++ ++ ++ false ++ Show desktop on hover ++ Show the desktop on mouse hover ++ ++ ++ 1000 ++ Delay show desktop ++ Delay before showing the desktop ++ ++ ++ 300 ++ Show desktop animation time ++ Window fade animation time when showing the destop ++ ++ ++ false ++ Show appMenu button ++ Show appMenu on the right hand side of the panel ++ ++ ++ true ++ Show window preview ++ Show preview of running window on hover of app icon ++ ++ ++ true ++ Show tooltip ++ Show tooltip on hover of app icon ++ ++ ++ true ++ Show running apps ++ Show or hide running application icons in the dash ++ ++ ++ true ++ Show favorites apps ++ Show or hide favorite application icons in the dash ++ ++ ++ 400 ++ Icon enter display time ++ Amount of time after entering icon to wait before displaying window preview if icon is not clicked or mouse has not left. ++ ++ ++ true ++ Enable peek mode ++ Peek a window upon hover for some time ++ ++ ++ true ++ Display title in preview ++ Display window title in preview ++ ++ ++ false ++ Window previews manual styling ++ This defines if the default window previews styling should be applied ++ ++ ++ 'TOP' ++ Title position ++ Position of the window title, close button and icon in preview. ++ ++ ++ "#dddddd" ++ Window previews title font color ++ This defines the window preview titles font color. ++ ++ ++ 14 ++ Window previews title font size ++ This defines the window preview titles font size. ++ ++ ++ false ++ Window previews use custom icon size ++ Window previews use custom application icon size. ++ ++ ++ 16 ++ Window previews custom icon size ++ Window previews custom application icon size. ++ ++ ++ 260 ++ Window previews animation time ++ This defines the window previews animation time. ++ ++ ++ 'inherit' ++ Font weight of window preview titles ++ This defines the font weight of window preview titles. Supported values: inherit (from theme), normal, lighter, bold and bolder. ++ ++ ++ 240 ++ Window previews size ++ Preferred window previews size ++ ++ ++ false ++ Fixed aspect ratio X ++ This defines if the window previews use a fixed aspect ratio X. ++ ++ ++ true ++ Fixed aspect ratio Y ++ This defines if the window previews use a fixed aspect ratio Y. ++ ++ ++ 8 ++ Window previews padding ++ The padding of the window previews ++ ++ ++ 16 ++ Aspect ratio X ++ The window previews respected aspect ratio X. ++ ++ ++ 9 ++ Aspect ratio Y ++ The window previews respected aspect ratio Y. ++ ++ ++ false ++ Immediate hide on icon click ++ The window previews immediately hide when an application icon is clicked. ++ ++ ++ false ++ Provide workspace isolation ++ Dash shows only windows from the current workspace ++ ++ ++ false ++ Close overview by clicking in empty space ++ Close overview or app grid by clicking in empty space ++ ++ ++ true ++ Group applications ++ Dash groups the application instances under the same icon ++ ++ ++ 14 ++ Application title font size ++ When the applications are ungrouped, this defines the application titles font size. ++ ++ ++ 'inherit' ++ Font weight of application titles ++ When the applications are ungrouped, this defines font weight of application titles. Supported values: inherit (from theme), normal, lighter, bold and bolder. ++ ++ ++ "#dddddd" ++ Application title font color ++ When the applications are ungrouped, this defines the application titles font color. ++ ++ ++ "#dddddd" ++ Minimized application title font color ++ When the applications are ungrouped, this defines the titles font color for minimized applications. ++ ++ ++ 160 ++ Application title max width ++ When the applications are ungrouped, this defines the application titles maximum width. ++ ++ ++ true ++ Use a fixed width for the application titles ++ The application titles all have the same width, even if their texts are shorter than the maximum width. The maximum width value is used as the fixed width. ++ ++ ++ true ++ Display running indicators on unfocused applications ++ When the applications are ungrouped, this defines if running applications should display an indicator. ++ ++ ++ false ++ Use favorite icons as application launchers ++ When the applications are ungrouped, this defines if running applications stay separate from the favorite icons. ++ ++ ++ 0 ++ Primary monitor index ++ Specifies the index of the primary monitor. ++ ++ ++ true ++ Display panels on all monitors ++ Specifies if a panel is shown on every monitors ++ ++ ++ [] ++ Available monitors ++ Available gnome-shell (Mutter) monitors, internal use ++ ++ ++ false ++ Provide monitor isolation ++ Dash shows only windows from the current monitor ++ ++ ++ true ++ Display the favorites on all monitors ++ Specifies if every panel should display the favorite applications. If false, the favorite appplications are only displayed on the primary monitor. ++ ++ ++ true ++ Customize click behaviour ++ Customize action on various mouse events ++ ++ ++ true ++ Minimize on shift+click ++ ++ ++ true ++ Activate only one window ++ ++ ++ 'CYCLE-MIN' ++ Action when clicking on a running app ++ Set the action that is executed when clicking on the icon of a running application ++ ++ ++ 'MINIMIZE' ++ Action when shift+clicking on a running app ++ Set the action that is executed when shift+clicking on the icon of a running application ++ ++ ++ 'LAUNCH' ++ Action when clicking on a running app ++ Set the action that is executed when middle-clicking on the icon of a running application ++ ++ ++ 'LAUNCH' ++ Action when clicking on a running app ++ Set the action that is executed when shift+middle-clicking on the icon of a running application ++ ++ ++ 'SWITCH_WORKSPACE' ++ Action when scrolling over the panel ++ Set the action that is executed when scrolling over the panel ++ ++ ++ 0 ++ Delay between panel mouse scroll events ++ Set the minimum delay between panel mouse scroll events ++ ++ ++ true ++ Show the workspace switch head-up when workspace is changed by scrolling on the panel ++ ++ ++ 'CYCLE_WINDOWS' ++ Action when scrolling over a running app ++ Set the action that is executed when scrolling over a running application ++ ++ ++ 0 ++ Delay between icon mouse scroll events ++ Set the minimum delay between icon mouse scroll events ++ ++ ++ 100 ++ Icon leave preview timeout ++ Amount of time to leave preview windows open when the mouse has left the application's icon. ++ ++ ++ 500 ++ Enter window peeking mode timeout ++ Amount of time of inactivity to enter the window peeking mode when the mouse has entered a window preview. ++ ++ ++ 40 ++ Window peeking mode opacity ++ All windows except for the peeked one have their opacity set to the same value. ++ ++ ++ true ++ Middle click preview to close window ++ Middle click on the window preview to close that window ++ ++ ++ true ++ Window previews use custom opacity ++ Window previews background use a different opacity from the panel ++ ++ ++ 80 ++ Window previews background opacity ++ Window previews use this custom background opacity. ++ ++ ++ 0 ++ Tray font size ++ Set the size of the tray font. (0 for default) ++ ++ ++ 0 ++ Leftbox font size ++ Set the size of the leftBox font. (0 for default) ++ ++ ++ 8 ++ App icon margin ++ Set the margin for application icons in the embedded dash. ++ ++ ++ 4 ++ App icon padding ++ Set the padding for application icons in the embedded dash. ++ ++ ++ -1 ++ Tray item padding ++ Set the size of the tray padding. (-1 for default) ++ ++ ++ -1 ++ Leftbox item padding ++ Set the size of the leftBox padding. (-1 for default) ++ ++ ++ -1 ++ Status icon padding ++ Set the size of the aggregate (status) menu icon padding. (-1 for default) ++ ++ ++ true ++ Animate running indicator when open/closing/switching applications ++ ++ ++ true ++ Animate when new window launched ++ ++ ++ false ++ Animate app icon on hover ++ ++ ++ 'SIMPLE' ++ App icon hover animation type ++ ++ ++ {'RIPPLE':2,'PLANK':1} ++ App icon hover animation curve convexity (1 is linear, more is convex, less is concave) ++ ++ ++ {'SIMPLE':160,'RIPPLE':130,'PLANK':100} ++ App icon hover animation duration in milliseconds ++ ++ ++ {'RIPPLE':4,'PLANK':4} ++ App icon hover animation extent (maximum number of animated icons) ++ ++ ++ {'SIMPLE':0,'RIPPLE':10,'PLANK':0} ++ App icon hover animation rotation in degrees ++ ++ ++ {'SIMPLE':0.30,'RIPPLE':0.40,'PLANK':0} ++ App icon hover animation travel translation in relation to the app icon size ++ ++ ++ {'SIMPLE':1,'RIPPLE':1.25,'PLANK':2} ++ App icon hover animation zoom scale in relation to the app icon size ++ ++ ++ true ++ Integrate items from the gnome appmenu into the right click menu ++ ++ ++ false ++ Display Show Details to open Gnome Software from right click menu ++ ++ ++ "<Super>q" ++ Keybinding to show the dock and the number overlay. ++ Behavior depends on hotkeys-show-dock and hotkeys-overlay. ++ ++ ++ q']]]> ++ Keybinding to show the dock and the number overlay. ++ Behavior depends on hotkeys-show-dock and hotkeys-overlay. ++ ++ ++ 2000 ++ Timeout to hide the dock, in seconds ++ Sets the time duration before the dock is hidden again. ++ ++ ++ 750 ++ Timeout to hide the dock, in seconds ++ Sets the time duration before the dock is hidden again. ++ ++ ++ 'TEMPORARILY' ++ Transitivity of the number overlay ++ You can choose between NEVER, TEMPORARILY and ALWAYS. ++ ++ ++ false ++ Super Hot-Keys ++ Launch and switch between dash items using Super+(0-9) ++ ++ ++ 'Super' ++ Prefix to use for hotkeys ++ You can choose between Super or SuperAlt as the prefix for hotkeys. ++ ++ ++ false ++ Show window previews ++ When multiple instances of the application are available, show their window previews ++ ++ ++ 'BOTH' ++ Hotkeys number keys ++ Which number keys are used for the hotkeys ++ ++ ++ 1']]]> ++ Keybinding to launch 1st dash app ++ ++ Keybinding to launch 1st app. ++ ++ ++ ++ 2']]]> ++ Keybinding to launch 2nd dash app ++ ++ Keybinding to launch 2nd app. ++ ++ ++ ++ 3']]]> ++ Keybinding to launch 3rd dash app ++ ++ Keybinding to launch 3rd app. ++ ++ ++ ++ 4']]]> ++ Keybinding to launch 4th dash app ++ ++ Keybinding to launch 4th app. ++ ++ ++ ++ 5']]]> ++ Keybinding to launch 5th dash app ++ ++ Keybinding to launch 5th app. ++ ++ ++ ++ 6']]]> ++ Keybinding to launch 6th dash app ++ ++ Keybinding to launch 6th app. ++ ++ ++ ++ 7']]]> ++ Keybinding to launch 7th dash app ++ ++ Keybinding to launch 7th app. ++ ++ ++ ++ 8']]]> ++ Keybinding to launch 8th dash app ++ ++ Keybinding to launch 8th app. ++ ++ ++ ++ 9']]]> ++ Keybinding to launch 9th dash app ++ ++ Keybinding to launch 9th app. ++ ++ ++ ++ 0']]]> ++ Keybinding to launch 10th dash app ++ ++ Keybinding to launch 10th app. ++ ++ ++ ++ 1']]]> ++ Keybinding to trigger 1st dash app with shift behavior ++ ++ Keybinding to trigger 1st app with shift behavior. ++ ++ ++ ++ 2']]]> ++ Keybinding to trigger 2nd dash app with shift behavior ++ ++ Keybinding to trigger 2nd app with shift behavior. ++ ++ ++ ++ 3']]]> ++ Keybinding to trigger 3rd dash app with shift behavior ++ ++ Keybinding to trigger 3rd app with shift behavior. ++ ++ ++ ++ 4']]]> ++ Keybinding to trigger 4th dash app with shift behavior ++ ++ Keybinding to trigger 4th app with shift behavior. ++ ++ ++ ++ 5']]]> ++ Keybinding to trigger 5th dash app with shift behavior ++ ++ Keybinding to trigger 5th app with shift behavior. ++ ++ ++ ++ 6']]]> ++ Keybinding to trigger 6th dash app with shift behavior ++ ++ Keybinding to trigger 6th app with shift behavior. ++ ++ ++ ++ 7']]]> ++ Keybinding to trigger 7th dash app with shift behavior ++ ++ Keybinding to trigger 7th app with shift behavior. ++ ++ ++ ++ 8']]]> ++ Keybinding to trigger 8th dash app with shift behavior ++ ++ Keybinding to trigger 8th app with shift behavior. ++ ++ ++ ++ 9']]]> ++ Keybinding to trigger 9th dash app with shift behavior ++ ++ Keybinding to trigger 9th app with shift behavior. ++ ++ ++ ++ 0']]]> ++ Keybinding to trigger 10th dash app with shift behavior ++ ++ Keybinding to trigger 10th app with shift behavior. ++ ++ ++ ++ 1']]]> ++ Keybinding to trigger 1st dash app ++ ++ Keybinding to either show or launch the 1st application in the dash. ++ ++ ++ ++ 2']]]> ++ Keybinding to trigger 2nd dash app ++ ++ Keybinding to either show or launch the 2nd application in the dash. ++ ++ ++ ++ 3']]]> ++ Keybinding to trigger 3rd dash app ++ ++ Keybinding to either show or launch the 3rd application in the dash. ++ ++ ++ ++ 4']]]> ++ Keybinding to trigger 4th dash app ++ ++ Keybinding to either show or launch the 4th application in the dash. ++ ++ ++ ++ 5']]]> ++ Keybinding to trigger 5th dash app ++ ++ Keybinding to either show or launch the 5th application in the dash. ++ ++ ++ ++ 6']]]> ++ Keybinding to trigger 6th dash app ++ ++ Keybinding to either show or launch the 6th application in the dash. ++ ++ ++ ++ 7']]]> ++ Keybinding to trigger 7th dash app ++ ++ Keybinding to either show or launch the 7th application in the dash. ++ ++ ++ ++ 8']]]> ++ Keybinding to trigger 8th dash app ++ ++ Keybinding to either show or launch the 8th application in the dash. ++ ++ ++ ++ 9']]]> ++ Keybinding to trigger 9th dash app ++ ++ Keybinding to either show or launch the 9th application in the dash. ++ ++ ++ ++ 0']]]> ++ Keybinding to trigger 10th dash app ++ ++ Keybinding to either show or launch the 10th application in the dash. ++ ++ ++ ++ KP_1']]]> ++ Keybinding to launch 1st dash app ++ ++ Keybinding to launch 1st app. ++ ++ ++ ++ KP_2']]]> ++ Keybinding to launch 2nd dash app ++ ++ Keybinding to launch 2nd app. ++ ++ ++ ++ KP_3']]]> ++ Keybinding to launch 3rd dash app ++ ++ Keybinding to launch 3rd app. ++ ++ ++ ++ KP_4']]]> ++ Keybinding to launch 4th dash app ++ ++ Keybinding to launch 4th app. ++ ++ ++ ++ KP_5']]]> ++ Keybinding to launch 5th dash app ++ ++ Keybinding to launch 5th app. ++ ++ ++ ++ KP_6']]]> ++ Keybinding to launch 6th dash app ++ ++ Keybinding to launch 6th app. ++ ++ ++ ++ KP_7']]]> ++ Keybinding to launch 7th dash app ++ ++ Keybinding to launch 7th app. ++ ++ ++ ++ KP_8']]]> ++ Keybinding to launch 8th dash app ++ ++ Keybinding to launch 8th app. ++ ++ ++ ++ KP_9']]]> ++ Keybinding to launch 9th dash app ++ ++ Keybinding to launch 9th app. ++ ++ ++ ++ KP_0']]]> ++ Keybinding to launch 10th dash app ++ ++ Keybinding to launch 10th app. ++ ++ ++ ++ KP_1']]]> ++ Keybinding to trigger 1st dash app with shift behavior ++ ++ Keybinding to trigger 1st app with shift behavior. ++ ++ ++ ++ KP_2']]]> ++ Keybinding to trigger 2nd dash app with shift behavior ++ ++ Keybinding to trigger 2nd app with shift behavior. ++ ++ ++ ++ KP_3']]]> ++ Keybinding to trigger 3rd dash app with shift behavior ++ ++ Keybinding to trigger 3rd app with shift behavior. ++ ++ ++ ++ KP_4']]]> ++ Keybinding to trigger 4th dash app with shift behavior ++ ++ Keybinding to trigger 4th app with shift behavior. ++ ++ ++ ++ KP_5']]]> ++ Keybinding to trigger 5th dash app with shift behavior ++ ++ Keybinding to trigger 5th app with shift behavior. ++ ++ ++ ++ KP_6']]]> ++ Keybinding to trigger 6th dash app with shift behavior ++ ++ Keybinding to trigger 6th app with shift behavior. ++ ++ ++ ++ KP_7']]]> ++ Keybinding to trigger 7th dash app with shift behavior ++ ++ Keybinding to trigger 7th app with shift behavior. ++ ++ ++ ++ KP_8']]]> ++ Keybinding to trigger 8th dash app with shift behavior ++ ++ Keybinding to trigger 8th app with shift behavior. ++ ++ ++ ++ KP_9']]]> ++ Keybinding to trigger 9th dash app with shift behavior ++ ++ Keybinding to trigger 9th app with shift behavior. ++ ++ ++ ++ KP_0']]]> ++ Keybinding to trigger 10th dash app with shift behavior ++ ++ Keybinding to trigger 10th app with shift behavior. ++ ++ ++ ++ KP_1']]]> ++ Keybinding to trigger 1st dash app ++ ++ Keybinding to either show or launch the 1st application in the dash. ++ ++ ++ ++ KP_2']]]> ++ Keybinding to trigger 2nd dash app ++ ++ Keybinding to either show or launch the 2nd application in the dash. ++ ++ ++ ++ KP_3']]]> ++ Keybinding to trigger 3rd dash app ++ ++ Keybinding to either show or launch the 3rd application in the dash. ++ ++ ++ ++ KP_4']]]> ++ Keybinding to trigger 4th dash app ++ ++ Keybinding to either show or launch the 4th application in the dash. ++ ++ ++ ++ KP_5']]]> ++ Keybinding to trigger 5th dash app ++ ++ Keybinding to either show or launch the 5th application in the dash. ++ ++ ++ ++ KP_6']]]> ++ Keybinding to trigger 6th dash app ++ ++ Keybinding to either show or launch the 6th application in the dash. ++ ++ ++ ++ KP_7']]]> ++ Keybinding to trigger 7th dash app ++ ++ Keybinding to either show or launch the 7th application in the dash. ++ ++ ++ ++ KP_8']]]> ++ Keybinding to trigger 8th dash app ++ ++ Keybinding to either show or launch the 8th application in the dash. ++ ++ ++ ++ KP_9']]]> ++ Keybinding to trigger 9th dash app ++ ++ Keybinding to either show or launch the 9th application in the dash. ++ ++ ++ ++ KP_0']]]> ++ Keybinding to trigger 10th dash app ++ ++ Keybinding to either show or launch the 10th application in the dash. ++ ++ ++ ++ true ++ Show progress bar on app icon ++ Whether to show progress bar overlay on app icon, for supported applications. ++ ++ ++ true ++ Show badge count on app icon ++ Whether to show badge count overlay on app icon, for supported applications. ++ ++ ++ +diff --git a/extensions/dash-to-panel/overview.js b/extensions/dash-to-panel/overview.js +new file mode 100644 +index 00000000..ac66c1d8 +--- /dev/null ++++ b/extensions/dash-to-panel/overview.js +@@ -0,0 +1,536 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Intellihide = Me.imports.intellihide; ++const Utils = Me.imports.utils; ++ ++const Clutter = imports.gi.Clutter; ++const Lang = imports.lang; ++const Main = imports.ui.main; ++const Shell = imports.gi.Shell; ++const Gtk = imports.gi.Gtk; ++const Gdk = imports.gi.Gdk; ++const Gio = imports.gi.Gio; ++const Mainloop = imports.mainloop; ++const IconGrid = imports.ui.iconGrid; ++const ViewSelector = imports.ui.viewSelector; ++ ++const Meta = imports.gi.Meta; ++ ++const GS_HOTKEYS_KEY = 'switch-to-application-'; ++ ++//timeout names ++const T1 = 'swipeEndTimeout'; ++ ++var dtpOverview = Utils.defineClass({ ++ Name: 'DashToPanel.Overview', ++ ++ _init: function() { ++ this._numHotkeys = 10; ++ this._timeoutsHandler = new Utils.TimeoutsHandler(); ++ }, ++ ++ enable : function(panel) { ++ this._panel = panel; ++ this.taskbar = panel.taskbar; ++ ++ this._injectionsHandler = new Utils.InjectionsHandler(); ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this._optionalWorkspaceIsolation(); ++ this._optionalHotKeys(); ++ this._optionalNumberOverlay(); ++ this._optionalClickToExit(); ++ this._toggleDash(); ++ ++ this._signalsHandler.add([ ++ Me.settings, ++ 'changed::stockgs-keep-dash', ++ () => this._toggleDash() ++ ]); ++ }, ++ ++ disable: function () { ++ this._signalsHandler.destroy(); ++ this._injectionsHandler.destroy(); ++ ++ this._toggleDash(true); ++ ++ // Remove key bindings ++ this._disableHotKeys(); ++ this._disableExtraShortcut(); ++ this._disableClickToExit(); ++ }, ++ ++ _toggleDash: function(visible) { ++ // To hide the dash, set its width to 1, so it's almost not taken into account by code ++ // calculaing the reserved space in the overview. The reason to keep it at 1 is ++ // to allow its visibility change to trigger an allocaion of the appGrid which ++ // in turn is triggergin the appsIcon spring animation, required when no other ++ // actors has this effect, i.e in horizontal mode and without the workspaceThumnails ++ // 1 static workspace only) ++ ++ if (visible === undefined) { ++ visible = Me.settings.get_boolean('stockgs-keep-dash'); ++ } ++ ++ let visibilityFunc = visible ? 'show' : 'hide'; ++ let width = visible ? -1 : 1; ++ let overviewControls = Main.overview._overview._controls || Main.overview._controls; ++ ++ overviewControls.dash.actor[visibilityFunc](); ++ overviewControls.dash.actor.set_width(width); ++ ++ // This force the recalculation of the icon size ++ overviewControls.dash._maxHeight = -1; ++ }, ++ ++ /** ++ * Isolate overview to open new windows for inactive apps ++ */ ++ _optionalWorkspaceIsolation: function() { ++ let label = 'optionalWorkspaceIsolation'; ++ ++ this._signalsHandler.add([ ++ Me.settings, ++ 'changed::isolate-workspaces', ++ Lang.bind(this, function() { ++ this._panel.panelManager.allPanels.forEach(p => p.taskbar.resetAppIcons()); ++ ++ if (Me.settings.get_boolean('isolate-workspaces')) ++ Lang.bind(this, enable)(); ++ else ++ Lang.bind(this, disable)(); ++ }) ++ ]); ++ ++ if (Me.settings.get_boolean('isolate-workspaces')) ++ Lang.bind(this, enable)(); ++ ++ function enable() { ++ this._injectionsHandler.removeWithLabel(label); ++ ++ this._injectionsHandler.addWithLabel(label, [ ++ Shell.App.prototype, ++ 'activate', ++ IsolatedOverview ++ ]); ++ ++ this._signalsHandler.removeWithLabel(label); ++ ++ this._signalsHandler.addWithLabel(label, [ ++ global.window_manager, ++ 'switch-workspace', ++ () => this._panel.panelManager.allPanels.forEach(p => p.taskbar.handleIsolatedWorkspaceSwitch()) ++ ]); ++ } ++ ++ function disable() { ++ this._signalsHandler.removeWithLabel(label); ++ this._injectionsHandler.removeWithLabel(label); ++ } ++ ++ function IsolatedOverview() { ++ // These lines take care of Nautilus for icons on Desktop ++ let activeWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++ let windows = this.get_windows().filter(w => w.get_workspace().index() == activeWorkspace.index()); ++ ++ if (windows.length > 0 && ++ (!(windows.length == 1 && windows[0].skip_taskbar) || ++ this.is_on_workspace(activeWorkspace))) ++ return Main.activateWindow(windows[0]); ++ ++ return this.open_new_window(-1); ++ } ++ }, ++ ++ // Hotkeys ++ _activateApp: function(appIndex) { ++ let seenApps = {}; ++ let apps = []; ++ ++ this.taskbar._getAppIcons().forEach(function(appIcon) { ++ if (!seenApps[appIcon.app]) { ++ apps.push(appIcon); ++ } ++ ++ seenApps[appIcon.app] = (seenApps[appIcon.app] || 0) + 1; ++ }); ++ ++ this._showOverlay(); ++ ++ if (appIndex < apps.length) { ++ let appIcon = apps[appIndex]; ++ let seenAppCount = seenApps[appIcon.app]; ++ let windowCount = appIcon.window || appIcon._hotkeysCycle ? seenAppCount : appIcon._nWindows; ++ ++ if (Me.settings.get_boolean('shortcut-previews') && windowCount > 1 && ++ !(Clutter.get_current_event().get_state() & ~(Clutter.ModifierType.MOD1_MASK | Clutter.ModifierType.MOD4_MASK))) { //ignore the alt (MOD1_MASK) and super key (MOD4_MASK) ++ if (this._hotkeyPreviewCycleInfo && this._hotkeyPreviewCycleInfo.appIcon != appIcon) { ++ this._endHotkeyPreviewCycle(); ++ } ++ ++ if (!this._hotkeyPreviewCycleInfo) { ++ this._hotkeyPreviewCycleInfo = { ++ appIcon: appIcon, ++ currentWindow: appIcon.window, ++ keyFocusOutId: appIcon.actor.connect('key-focus-out', () => appIcon.actor.grab_key_focus()), ++ capturedEventId: global.stage.connect('captured-event', (actor, e) => { ++ if (e.type() == Clutter.EventType.KEY_RELEASE && e.get_key_symbol() == (Clutter.KEY_Super_L || Clutter.Super_L)) { ++ this._endHotkeyPreviewCycle(true); ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ }) ++ }; ++ ++ appIcon._hotkeysCycle = appIcon.window; ++ appIcon.window = null; ++ appIcon._previewMenu.open(appIcon); ++ appIcon.actor.grab_key_focus(); ++ } ++ ++ appIcon._previewMenu.focusNext(); ++ } else { ++ // Activate with button = 1, i.e. same as left click ++ let button = 1; ++ this._endHotkeyPreviewCycle(); ++ appIcon.activate(button, true); ++ } ++ } ++ }, ++ ++ _endHotkeyPreviewCycle: function(focusWindow) { ++ if (this._hotkeyPreviewCycleInfo) { ++ global.stage.disconnect(this._hotkeyPreviewCycleInfo.capturedEventId); ++ this._hotkeyPreviewCycleInfo.appIcon.actor.disconnect(this._hotkeyPreviewCycleInfo.keyFocusOutId); ++ ++ if (focusWindow) { ++ this._hotkeyPreviewCycleInfo.appIcon._previewMenu.activateFocused(); ++ } ++ ++ this._hotkeyPreviewCycleInfo.appIcon.window = this._hotkeyPreviewCycleInfo.currentWindow; ++ delete this._hotkeyPreviewCycleInfo.appIcon._hotkeysCycle; ++ this._hotkeyPreviewCycleInfo = 0; ++ } ++ }, ++ ++ _optionalHotKeys: function() { ++ this._hotKeysEnabled = false; ++ if (Me.settings.get_boolean('hot-keys')) ++ this._enableHotKeys(); ++ ++ this._signalsHandler.add([ ++ Me.settings, ++ 'changed::hot-keys', ++ Lang.bind(this, function() { ++ if (Me.settings.get_boolean('hot-keys')) ++ Lang.bind(this, this._enableHotKeys)(); ++ else ++ Lang.bind(this, this._disableHotKeys)(); ++ }) ++ ]); ++ }, ++ ++ _resetHotkeys: function() { ++ this._disableHotKeys(); ++ this._enableHotKeys(); ++ }, ++ ++ _enableHotKeys: function() { ++ if (this._hotKeysEnabled) ++ return; ++ ++ //3.32 introduced app hotkeys, disable them to prevent conflicts ++ if (Main.wm._switchToApplication) { ++ for (let i = 1; i < 10; ++i) { ++ Utils.removeKeybinding(GS_HOTKEYS_KEY + i); ++ } ++ } ++ ++ // Setup keyboard bindings for taskbar elements ++ let shortcutNumKeys = Me.settings.get_string('shortcut-num-keys'); ++ let bothNumKeys = shortcutNumKeys == 'BOTH'; ++ let keys = []; ++ ++ if (bothNumKeys || shortcutNumKeys == 'NUM_ROW') { ++ keys.push('app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-'); // Regular numbers ++ } ++ ++ if (bothNumKeys || shortcutNumKeys == 'NUM_KEYPAD') { ++ keys.push('app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-'); // Key-pad numbers ++ } ++ ++ keys.forEach( function(key) { ++ for (let i = 0; i < this._numHotkeys; i++) { ++ let appNum = i; ++ ++ Utils.addKeybinding(key + (i + 1), Me.settings, () => this._activateApp(appNum)); ++ } ++ }, this); ++ ++ this._hotKeysEnabled = true; ++ ++ if (Me.settings.get_string('hotkeys-overlay-combo') === 'ALWAYS') ++ this.taskbar.toggleNumberOverlay(true); ++ }, ++ ++ _disableHotKeys: function() { ++ if (!this._hotKeysEnabled) ++ return; ++ ++ let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-', // Regular numbers ++ 'app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-']; // Key-pad numbers ++ keys.forEach( function(key) { ++ for (let i = 0; i < this._numHotkeys; i++) { ++ Utils.removeKeybinding(key + (i + 1)); ++ } ++ }, this); ++ ++ if (Main.wm._switchToApplication) { ++ let gsSettings = new Gio.Settings({ schema_id: imports.ui.windowManager.SHELL_KEYBINDINGS_SCHEMA }); ++ ++ for (let i = 1; i < 10; ++i) { ++ Utils.addKeybinding(GS_HOTKEYS_KEY + i, gsSettings, Main.wm._switchToApplication.bind(Main.wm)); ++ } ++ } ++ ++ this._hotKeysEnabled = false; ++ ++ this.taskbar.toggleNumberOverlay(false); ++ }, ++ ++ _optionalNumberOverlay: function() { ++ // Enable extra shortcut ++ if (Me.settings.get_boolean('hot-keys')) ++ this._enableExtraShortcut(); ++ ++ this._signalsHandler.add([ ++ Me.settings, ++ 'changed::hot-keys', ++ Lang.bind(this, this._checkHotkeysOptions) ++ ], [ ++ Me.settings, ++ 'changed::hotkeys-overlay-combo', ++ Lang.bind(this, function() { ++ if (Me.settings.get_boolean('hot-keys') && Me.settings.get_string('hotkeys-overlay-combo') === 'ALWAYS') ++ this.taskbar.toggleNumberOverlay(true); ++ else ++ this.taskbar.toggleNumberOverlay(false); ++ }) ++ ], [ ++ Me.settings, ++ 'changed::shortcut-num-keys', ++ () => this._resetHotkeys() ++ ]); ++ }, ++ ++ _checkHotkeysOptions: function() { ++ if (Me.settings.get_boolean('hot-keys')) ++ this._enableExtraShortcut(); ++ else ++ this._disableExtraShortcut(); ++ }, ++ ++ _enableExtraShortcut: function() { ++ Utils.addKeybinding('shortcut', Me.settings, () => this._showOverlay(true)); ++ }, ++ ++ _disableExtraShortcut: function() { ++ Utils.removeKeybinding('shortcut'); ++ }, ++ ++ _showOverlay: function(overlayFromShortcut) { ++ //wait for intellihide timeout initialization ++ if (!this._panel.intellihide) { ++ return; ++ } ++ ++ // Restart the counting if the shortcut is pressed again ++ if (this._numberOverlayTimeoutId) { ++ Mainloop.source_remove(this._numberOverlayTimeoutId); ++ this._numberOverlayTimeoutId = 0; ++ } ++ ++ let hotkey_option = Me.settings.get_string('hotkeys-overlay-combo'); ++ ++ if (hotkey_option === 'NEVER') ++ return; ++ ++ if (hotkey_option === 'TEMPORARILY' || overlayFromShortcut) ++ this.taskbar.toggleNumberOverlay(true); ++ ++ this._panel.intellihide.revealAndHold(Intellihide.Hold.TEMPORARY); ++ ++ let timeout = Me.settings.get_int('overlay-timeout'); ++ ++ if (overlayFromShortcut) { ++ timeout = Me.settings.get_int('shortcut-timeout'); ++ } ++ ++ // Hide the overlay/dock after the timeout ++ this._numberOverlayTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, function() { ++ this._numberOverlayTimeoutId = 0; ++ ++ if (hotkey_option != 'ALWAYS') { ++ this.taskbar.toggleNumberOverlay(false); ++ } ++ ++ this._panel.intellihide.release(Intellihide.Hold.TEMPORARY); ++ })); ++ }, ++ ++ _optionalClickToExit: function() { ++ this._clickToExitEnabled = false; ++ if (Me.settings.get_boolean('overview-click-to-exit')) ++ this._enableClickToExit(); ++ ++ this._signalsHandler.add([ ++ Me.settings, ++ 'changed::overview-click-to-exit', ++ Lang.bind(this, function() { ++ if (Me.settings.get_boolean('overview-click-to-exit')) ++ Lang.bind(this, this._enableClickToExit)(); ++ else ++ Lang.bind(this, this._disableClickToExit)(); ++ }) ++ ]); ++ }, ++ ++ _enableClickToExit: function() { ++ if (this._clickToExitEnabled) ++ return; ++ ++ let views = Utils.getAppDisplayViews(); ++ this._oldOverviewReactive = Main.overview._overview.reactive ++ ++ Main.overview._overview.reactive = true; ++ ++ this._clickAction = new Clutter.ClickAction(); ++ this._clickAction.connect('clicked', () => { ++ ++ if (this._swiping) ++ return Clutter.EVENT_PROPAGATE; ++ ++ let [x, y] = global.get_pointer(); ++ let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); ++ ++ let activePage = Main.overview.viewSelector.getActivePage(); ++ if (activePage == ViewSelector.ViewPage.APPS) { ++ ++ if(pickedActor != Main.overview._overview ++ && (views.length > 1 && pickedActor != Main.overview.viewSelector.appDisplay._controls.get_parent()) ++ && pickedActor != (views[0].view.actor || views[0].view) ++ && (views.length > 1 && pickedActor != views[1].view._scrollView) ++ && (views.length > 1 && pickedActor != views[1].view._grid)) { ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ if(Me.settings.get_boolean('animate-show-apps')) { ++ let view = Utils.find(views, v => v.view.actor.visible).view; ++ view.animate(IconGrid.AnimationDirection.OUT, Lang.bind(this, function() { ++ Main.overview.viewSelector._appsPage.hide(); ++ Main.overview.hide(); ++ })); ++ } else { ++ Main.overview.hide(); ++ } ++ } else if (activePage == ViewSelector.ViewPage.WINDOWS) { ++ let overviewControls = Main.overview._overview._controls || Main.overview._controls; ++ ++ if(pickedActor == overviewControls._thumbnailsBox ++ || pickedActor == overviewControls.dash._container) { ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ if (pickedActor instanceof Meta.BackgroundActor) { ++ Utils.find(overviewControls._thumbnailsBox._thumbnails, t => ++ pickedActor == t._bgManager.backgroundActor ++ ).activate(); ++ return Clutter.EVENT_STOP; ++ } ++ ++ Main.overview.toggle(); ++ } else { ++ Main.overview.toggle(); ++ } ++ }); ++ Main.overview._overview.add_action(this._clickAction); ++ ++ [Main.overview.viewSelector._workspacesDisplay].concat(views.map(v => v.view)).forEach(v => { ++ if (v._swipeTracker) { ++ this._signalsHandler.addWithLabel('clickToExit', [ ++ v._swipeTracker, ++ 'begin', ++ Lang.bind(this, this._onSwipeBegin) ++ ],[ ++ v._swipeTracker, ++ 'end', ++ Lang.bind(this, this._onSwipeEnd) ++ ]); ++ } else if (v._panAction) { ++ this._signalsHandler.addWithLabel('clickToExit', [ ++ v._panAction, ++ 'gesture-begin', ++ Lang.bind(this, this._onSwipeBegin) ++ ],[ ++ v._panAction, ++ 'gesture-cancel', ++ Lang.bind(this, this._onSwipeEnd) ++ ],[ ++ v._panAction, ++ 'gesture-end', ++ Lang.bind(this, this._onSwipeEnd) ++ ]); ++ } ++ }); ++ ++ this._clickToExitEnabled = true; ++ }, ++ ++ _disableClickToExit: function () { ++ if (!this._clickToExitEnabled) ++ return; ++ ++ Main.overview._overview.remove_action(this._clickAction); ++ Main.overview._overview.reactive = this._oldOverviewReactive; ++ ++ this._signalsHandler.removeWithLabel('clickToExit'); ++ ++ this._clickToExitEnabled = false; ++ }, ++ ++ _onSwipeBegin: function() { ++ this._swiping = true; ++ return true; ++ }, ++ ++ _onSwipeEnd: function() { ++ this._timeoutsHandler.add([ ++ T1, ++ 0, ++ () => this._swiping = false ++ ]); ++ return true; ++ } ++}); +diff --git a/extensions/dash-to-panel/panel.js b/extensions/dash-to-panel/panel.js +new file mode 100644 +index 00000000..a8c1a587 +--- /dev/null ++++ b/extensions/dash-to-panel/panel.js +@@ -0,0 +1,1563 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * ++ * Code to re-anchor the panel was taken from Thoma5 BottomPanel: ++ * https://github.com/Thoma5/gnome-shell-extension-bottompanel ++ * ++ * Pattern for moving clock based on Frippery Move Clock by R M Yorston ++ * http://frippery.org/extensions/ ++ * ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Clutter = imports.gi.Clutter; ++const Config = imports.misc.config; ++const Gtk = imports.gi.Gtk; ++const Gi = imports._gi; ++const AppIcons = Me.imports.appIcons; ++const Utils = Me.imports.utils; ++const Taskbar = Me.imports.taskbar; ++const Pos = Me.imports.panelPositions; ++const PanelSettings = Me.imports.panelSettings; ++const PanelStyle = Me.imports.panelStyle; ++const Lang = imports.lang; ++const Main = imports.ui.main; ++const Mainloop = imports.mainloop; ++const Dash = imports.ui.dash; ++const CtrlAltTab = imports.ui.ctrlAltTab; ++const Panel = imports.ui.panel; ++const PanelMenu = imports.ui.panelMenu; ++const St = imports.gi.St; ++const GLib = imports.gi.GLib; ++const Meta = imports.gi.Meta; ++const Pango = imports.gi.Pango; ++const DND = imports.ui.dnd; ++const Shell = imports.gi.Shell; ++const PopupMenu = imports.ui.popupMenu; ++const IconGrid = imports.ui.iconGrid; ++const ViewSelector = imports.ui.viewSelector; ++const DateMenu = imports.ui.dateMenu; ++const Volume = imports.ui.status.volume; ++const Progress = Me.imports.progress; ++ ++const Intellihide = Me.imports.intellihide; ++const Transparency = Me.imports.transparency; ++const _ = imports.gettext.domain(Me.imports.utils.TRANSLATION_DOMAIN).gettext; ++ ++let tracker = Shell.WindowTracker.get_default(); ++var panelBoxes = ['_leftBox', '_centerBox', '_rightBox']; ++ ++//timeout names ++const T1 = 'startDynamicTransparencyTimeout'; ++const T2 = 'startIntellihideTimeout'; ++const T3 = 'allocationThrottleTimeout'; ++const T4 = 'showDesktopTimeout'; ++const T5 = 'trackerFocusAppTimeout'; ++const T6 = 'scrollPanelDelayTimeout'; ++const T7 = 'waitPanelBoxAllocation'; ++ ++function setMenuArrow(arrowIcon, side) { ++ let parent = arrowIcon.get_parent(); ++ let iconNames = { ++ '0': 'pan-down-symbolic', //TOP ++ '1': 'pan-start-symbolic', //RIGHT ++ '2': 'pan-up-symbolic', //BOTTOM ++ '3': 'pan-end-symbolic' //LEFT ++ }; ++ ++ parent.remove_child(arrowIcon); ++ arrowIcon.set_icon_name(iconNames[side]); ++ parent.add_child(arrowIcon); ++} ++ ++var dtpPanel = Utils.defineClass({ ++ Name: 'DashToPanel-Panel', ++ Extends: St.Widget, ++ ++ _init: function(panelManager, monitor, panelBox, isStandalone) { ++ this.callParent('_init', { layout_manager: new Clutter.BinLayout() }); ++ ++ this._timeoutsHandler = new Utils.TimeoutsHandler(); ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this.panelManager = panelManager; ++ this.panelStyle = new PanelStyle.dtpPanelStyle(); ++ ++ this.monitor = monitor; ++ this.panelBox = panelBox; ++ ++ // when the original gnome-shell top panel is kept, all panels are "standalone", ++ // so in this case use isPrimary to get the panel on the primary dtp monitor, which ++ // might be different from the system's primary monitor. ++ this.isStandalone = isStandalone; ++ this.isPrimary = !isStandalone || (Me.settings.get_boolean('stockgs-keep-top-panel') && ++ monitor == panelManager.dtpPrimaryMonitor); ++ ++ this._sessionStyle = null; ++ this._unmappedButtons = []; ++ this._elementGroups = []; ++ this.cornerSize = 0; ++ ++ let position = this.getPosition(); ++ ++ if (isStandalone) { ++ this.panel = new dtpSecondaryPanel({ name: 'panel', reactive: true }); ++ this.statusArea = this.panel.statusArea = {}; ++ ++ Utils.wrapActor(this.panel); ++ ++ //next 3 functions are needed by other extensions to add elements to the secondary panel ++ this.panel.addToStatusArea = function(role, indicator, position, box) { ++ return Main.panel.addToStatusArea.call(this, role, indicator, position, box); ++ }; ++ ++ this.panel._addToPanelBox = function(role, indicator, position, box) { ++ Main.panel._addToPanelBox.call(this, role, indicator, position, box); ++ }; ++ ++ this.panel._onMenuSet = function(indicator) { ++ Main.panel._onMenuSet.call(this, indicator); ++ }; ++ ++ this._leftBox = this.panel._leftBox = new St.BoxLayout({ name: 'panelLeft' }); ++ this._centerBox = this.panel._centerBox = new St.BoxLayout({ name: 'panelCenter' }); ++ this._rightBox = this.panel._rightBox = new St.BoxLayout({ name: 'panelRight' }); ++ ++ this.menuManager = this.panel.menuManager = new PopupMenu.PopupMenuManager(this.panel); ++ ++ this._setPanelMenu('aggregateMenu', dtpSecondaryAggregateMenu, this.panel.actor); ++ this._setPanelMenu('dateMenu', DateMenu.DateMenuButton, this.panel.actor); ++ this._setPanelMenu('activities', Panel.ActivitiesButton, this.panel.actor); ++ ++ if (this.statusArea.aggregateMenu) { ++ setMenuArrow(this.statusArea.aggregateMenu._indicators.get_last_child(), position); ++ } ++ ++ this.panel.add_child(this._leftBox); ++ this.panel.add_child(this._centerBox); ++ this.panel.add_child(this._rightBox); ++ } else { ++ this.panel = Main.panel; ++ this.statusArea = Main.panel.statusArea; ++ this.menuManager = Main.panel.menuManager; ++ ++ setMenuArrow(this.statusArea.aggregateMenu._indicators.get_last_child(), position); ++ ++ panelBoxes.forEach(p => this[p] = Main.panel[p]); ++ ++ ['activities', 'aggregateMenu', 'dateMenu'].forEach(b => { ++ let container = this.statusArea[b].container; ++ let parent = container.get_parent(); ++ ++ container._dtpOriginalParent = parent; ++ parent ? parent.remove_child(container) : null; ++ this.panel.actor.add_child(container); ++ }); ++ } ++ ++ // Create a wrapper around the real showAppsIcon in order to add a popupMenu. Most of ++ // its behavior is handled by the taskbar, but its positioning is done at the panel level ++ this.showAppsIconWrapper = new AppIcons.ShowAppsIconWrapper(this); ++ this.panel.actor.add_child(this.showAppsIconWrapper.realShowAppsIcon); ++ ++ this.panel.actor._delegate = this; ++ ++ Utils.wrapActor(this.statusArea.activities); ++ ++ this.add_child(this.panel.actor); ++ ++ if (Main.panel._onButtonPress || Main.panel._tryDragWindow) { ++ this._signalsHandler.add([ ++ this.panel.actor, ++ [ ++ 'button-press-event', ++ 'touch-event' ++ ], ++ this._onButtonPress.bind(this) ++ ]); ++ } ++ ++ if (Main.panel._onKeyPress) { ++ this._signalsHandler.add([this.panel.actor, 'key-press-event', Main.panel._onKeyPress.bind(this)]); ++ } ++ ++ Main.ctrlAltTabManager.addGroup(this, _("Top Bar")+" "+ monitor.index, 'focus-top-bar-symbolic', ++ { sortGroup: CtrlAltTab.SortGroup.TOP }); ++ }, ++ ++ enable : function() { ++ let position = this.getPosition(); ++ ++ if (this.statusArea.aggregateMenu) { ++ Utils.getIndicators(this.statusArea.aggregateMenu._volume)._dtpIgnoreScroll = 1; ++ } ++ ++ this.geom = this.getGeometry(); ++ ++ // The overview uses the panel height as a margin by way of a "ghost" transparent Clone ++ // This pushes everything down, which isn't desired when the panel is moved to the bottom ++ // I'm adding a 2nd ghost panel and will resize the top or bottom ghost depending on the panel position ++ this._myPanelGhost = new Clutter.Actor({ ++ x: this.geom.x, ++ y: this.geom.y , ++ reactive: false, ++ opacity: 0 ++ }); ++ ++ let isTop = this.geom.position == St.Side.TOP; ++ ++ if (isTop) { ++ this.panel._leftCorner = this.panel._leftCorner || new Panel.PanelCorner(St.Side.LEFT); ++ this.panel._rightCorner = this.panel._rightCorner || new Panel.PanelCorner(St.Side.RIGHT); ++ ++ Main.overview._overview.insert_child_at_index(this._myPanelGhost, 0); ++ } else { ++ let overviewControls = Main.overview._overview._controls || Main.overview._controls; ++ ++ if (this.geom.position == St.Side.BOTTOM) { ++ Main.overview._overview.add_actor(this._myPanelGhost); ++ } else if (this.geom.position == St.Side.LEFT) { ++ overviewControls._group.insert_child_at_index(this._myPanelGhost, 0); ++ } else { ++ overviewControls._group.add_actor(this._myPanelGhost); ++ } ++ } ++ ++ if (this.panel._leftCorner) { ++ Utils.wrapActor(this.panel._leftCorner); ++ Utils.wrapActor(this.panel._rightCorner); ++ ++ if (isTop) { ++ if (this.isStandalone) { ++ this.panel.actor.add_child(this.panel._leftCorner.actor); ++ this.panel.actor.add_child(this.panel._rightCorner.actor); ++ } ++ } else if (Config.PACKAGE_VERSION >= '3.32') { ++ this.panel.actor.remove_child(this.panel._leftCorner.actor); ++ this.panel.actor.remove_child(this.panel._rightCorner.actor); ++ } ++ } ++ ++ this._setPanelPosition(); ++ ++ if (!this.isStandalone) { ++ if (this.panel.vfunc_allocate) { ++ this._panelConnectId = 0; ++ Utils.hookVfunc(this.panel.__proto__, 'allocate', (box, flags) => this._mainPanelAllocate(0, box, flags)); ++ } else { ++ this._panelConnectId = this.panel.actor.connect('allocate', (actor, box, flags) => this._mainPanelAllocate(actor, box, flags)); ++ } ++ ++ // remove the extra space before the clock when the message-indicator is displayed ++ if (DateMenu.IndicatorPad) { ++ Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_width', () => [0,0]); ++ Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_height', () => [0,0]); ++ } ++ } ++ ++ if (!DateMenu.IndicatorPad && this.statusArea.dateMenu) { ++ //3.36 switched to a size constraint applied on an anonymous child ++ let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child(); ++ ++ this._dateMenuIndicatorPadContraints = indicatorPad.get_constraints(); ++ indicatorPad.clear_constraints(); ++ } ++ ++ // The main panel's connection to the "allocate" signal is competing with this extension ++ // trying to move the centerBox over to the right, creating a never-ending cycle. ++ // Since we don't have the ID to disconnect that handler, wrap the allocate() function ++ // it calls instead. If the call didn't originate from this file, ignore it. ++ panelBoxes.forEach(b => { ++ this[b].allocate = (box, flags, isFromDashToPanel) => { ++ if (isFromDashToPanel) { ++ Utils.allocate(this[b], box, flags, true); ++ } ++ } ++ }); ++ ++ this.menuManager._oldChangeMenu = this.menuManager._changeMenu; ++ this.menuManager._changeMenu = (menu) => { ++ if (!Me.settings.get_boolean('stockgs-panelbtn-click-only')) { ++ this.menuManager._oldChangeMenu(menu); ++ } ++ }; ++ ++ if (this.statusArea.appMenu) { ++ setMenuArrow(this.statusArea.appMenu._arrow, position); ++ this._leftBox.remove_child(this.statusArea.appMenu.container); ++ } ++ ++ if (this.statusArea.keyboard) { ++ setMenuArrow(this.statusArea.keyboard._hbox.get_last_child(), position); ++ } ++ ++ this.dynamicTransparency = new Transparency.DynamicTransparency(this); ++ ++ this.taskbar = new Taskbar.taskbar(this); ++ ++ this.panel.actor.add_child(this.taskbar.actor); ++ ++ this._setAppmenuVisible(Me.settings.get_boolean('show-appmenu')); ++ this._setShowDesktopButton(true); ++ ++ this._setAllocationMap(); ++ ++ this.panel.actor.add_style_class_name('dashtopanelMainPanel ' + this.getOrientation()); ++ ++ // Since Gnome 3.8 dragging an app without having opened the overview before cause the attemp to ++ //animate a null target since some variables are not initialized when the viewSelector is created ++ if(Main.overview.viewSelector._activePage == null) ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._workspacesPage; ++ ++ this._setPanelGhostSize(); ++ ++ this._timeoutsHandler.add([T2, Me.settings.get_int('intellihide-enable-start-delay'), () => this.intellihide = new Intellihide.Intellihide(this)]); ++ ++ this._signalsHandler.add( ++ // this is to catch changes to the theme or window scale factor ++ [ ++ Utils.getStageTheme(), ++ 'changed', ++ () => (this._resetGeometry(), this._setShowDesktopButtonStyle()), ++ ], ++ [ ++ // sync hover after a popupmenu is closed ++ this.taskbar, ++ 'menu-closed', ++ Lang.bind(this, function(){this.panel.actor.sync_hover();}) ++ ], ++ [ ++ Main.overview, ++ [ ++ 'showing', ++ 'hiding' ++ ], ++ () => this._adjustForOverview() ++ ], ++ [ ++ Main.overview, ++ 'hidden', ++ () => { ++ if (this.isPrimary) { ++ //reset the primary monitor when exiting the overview ++ this.panelManager.setFocusedMonitor(this.monitor, true); ++ } ++ } ++ ], ++ [ ++ this.statusArea.activities.actor, ++ 'captured-event', ++ (actor, e) => { ++ if (e.type() == Clutter.EventType.BUTTON_PRESS || e.type() == Clutter.EventType.TOUCH_BEGIN) { ++ //temporarily use as primary the monitor on which the activities btn was clicked ++ this.panelManager.setFocusedMonitor(this.monitor, true); ++ } ++ } ++ ], ++ [ ++ this._centerBox, ++ 'actor-added', ++ () => this._onBoxActorAdded(this._centerBox) ++ ], ++ [ ++ this._rightBox, ++ 'actor-added', ++ () => this._onBoxActorAdded(this._rightBox) ++ ], ++ [ ++ this.panel.actor, ++ 'scroll-event', ++ this._onPanelMouseScroll.bind(this) ++ ], ++ [ ++ Main.layoutManager, ++ 'startup-complete', ++ () => this._resetGeometry() ++ ] ++ ); ++ ++ this._bindSettingsChanges(); ++ ++ this.panelStyle.enable(this); ++ ++ if (this.checkIfVertical()) { ++ this._signalsHandler.add([ ++ this.panelBox, ++ 'notify::visible', ++ () => { ++ if (this.panelBox.visible) { ++ this._refreshVerticalAlloc(); ++ } ++ } ++ ]); ++ ++ this._setSearchEntryOffset(this.geom.w); ++ ++ if (this.statusArea.dateMenu) { ++ this._formatVerticalClock(); ++ ++ this._signalsHandler.add([ ++ this.statusArea.dateMenu._clock, ++ 'notify::clock', ++ () => this._formatVerticalClock() ++ ]); ++ } ++ } ++ ++ // Since we are usually visible but not usually changing, make sure ++ // most repaint requests don't actually require us to repaint anything. ++ // This saves significant CPU when repainting the screen. ++ this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); ++ ++ this._initProgressManager(); ++ }, ++ ++ disable: function () { ++ this.panelStyle.disable(); ++ ++ this._timeoutsHandler.destroy(); ++ this._signalsHandler.destroy(); ++ this._disablePanelCornerSignals(); ++ ++ this.panel.actor.remove_child(this.taskbar.actor); ++ this._setAppmenuVisible(false); ++ ++ if (this.intellihide) { ++ this.intellihide.destroy(); ++ } ++ ++ this.dynamicTransparency.destroy(); ++ ++ this.progressManager.destroy(); ++ ++ this.taskbar.destroy(); ++ this.showAppsIconWrapper.destroy(); ++ ++ this.menuManager._changeMenu = this.menuManager._oldChangeMenu; ++ ++ this._myPanelGhost.get_parent().remove_actor(this._myPanelGhost); ++ this._setSearchEntryOffset(0); ++ ++ panelBoxes.forEach(b => delete this[b].allocate); ++ this._unmappedButtons.forEach(a => this._disconnectVisibleId(a)); ++ ++ if (this._dateMenuIndicatorPadContraints && this.statusArea.dateMenu) { ++ let indicatorPad = this.statusArea.dateMenu.get_first_child().get_first_child(); ++ ++ this._dateMenuIndicatorPadContraints.forEach(c => indicatorPad.add_constraint(c)); ++ } ++ ++ this._setVertical(this.panel.actor, false); ++ ++ if (!this.isStandalone) { ++ this.statusArea.dateMenu._clockDisplay.text = this.statusArea.dateMenu._clock.clock; ++ ++ ['vertical', 'horizontal', 'dashtopanelMainPanel'].forEach(c => this.panel.actor.remove_style_class_name(c)); ++ ++ if (!Main.sessionMode.isLocked) { ++ [['activities', 0], ['aggregateMenu', -1], ['dateMenu', 0]].forEach(b => { ++ let container = this.statusArea[b[0]].container; ++ let originalParent = container._dtpOriginalParent; ++ ++ this.panel.actor.remove_child(container); ++ originalParent ? originalParent.insert_child_at_index(container, b[1]) : null; ++ delete container._dtpOriginalParent; ++ }); ++ ++ if (this.statusArea.appMenu) { ++ setMenuArrow(this.statusArea.appMenu._arrow, St.Side.TOP); ++ this._leftBox.add_child(this.statusArea.appMenu.container); ++ } ++ ++ if (this.statusArea.keyboard) { ++ setMenuArrow(this.statusArea.keyboard._hbox.get_last_child(), St.Side.TOP); ++ } ++ } ++ ++ if (!this.panel._leftCorner.actor.mapped) { ++ this.panel.actor.add_child(this.panel._leftCorner.actor); ++ this.panel.actor.add_child(this.panel._rightCorner.actor); ++ } ++ ++ this._setShowDesktopButton(false); ++ ++ delete Utils.getIndicators(this.statusArea.aggregateMenu._volume)._dtpIgnoreScroll; ++ setMenuArrow(this.statusArea.aggregateMenu._indicators.get_last_child(), St.Side.TOP); ++ ++ if (DateMenu.IndicatorPad) { ++ Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_width', DateMenu.IndicatorPad.prototype.vfunc_get_preferred_width); ++ Utils.hookVfunc(DateMenu.IndicatorPad.prototype, 'get_preferred_height', DateMenu.IndicatorPad.prototype.vfunc_get_preferred_height); ++ } ++ ++ if (this._panelConnectId) { ++ this.panel.actor.disconnect(this._panelConnectId); ++ } else { ++ Utils.hookVfunc(this.panel.__proto__, 'allocate', this.panel.__proto__.vfunc_allocate); ++ } ++ ++ this.panel.actor._delegate = this.panel; ++ } else { ++ this._removePanelMenu('dateMenu'); ++ this._removePanelMenu('aggregateMenu'); ++ this._removePanelMenu('activities'); ++ } ++ ++ Main.ctrlAltTabManager.removeGroup(this); ++ }, ++ ++ handleDragOver: function(source, actor, x, y, time) { ++ if (source == Main.xdndHandler) { ++ ++ // open overview so they can choose a window for focusing ++ // and ultimately dropping dragged item onto ++ if(Main.overview.shouldToggleByCornerOrButton()) ++ Main.overview.show(); ++ } ++ ++ return DND.DragMotionResult.CONTINUE; ++ }, ++ ++ getPosition: function() { ++ let position = PanelSettings.getPanelPosition(Me.settings, this.monitor.index); ++ ++ if (position == Pos.TOP) { ++ return St.Side.TOP; ++ } else if (position == Pos.RIGHT) { ++ return St.Side.RIGHT; ++ } else if (position == Pos.BOTTOM) { ++ return St.Side.BOTTOM; ++ } ++ ++ return St.Side.LEFT; ++ }, ++ ++ checkIfVertical: function() { ++ let position = this.getPosition(); ++ ++ return (position == St.Side.LEFT || position == St.Side.RIGHT); ++ }, ++ ++ getOrientation: function() { ++ return (this.checkIfVertical() ? 'vertical' : 'horizontal'); ++ }, ++ ++ updateElementPositions: function() { ++ let panelPositions = this.panelManager.panelsElementPositions[this.monitor.index] || Pos.defaults; ++ ++ this._updateGroupedElements(panelPositions); ++ ++ this._disablePanelCornerSignals(); ++ ++ if (this.getPosition() == St.Side.TOP) { ++ let visibleElements = panelPositions.filter(pp => pp.visible); ++ let connectCorner = (corner, button) => { ++ corner._button = button; ++ corner._buttonStyleChangedSignalId = button.connect('style-changed', () => { ++ corner.set_style_pseudo_class(button.get_style_pseudo_class()); ++ }); ++ } ++ ++ if (visibleElements[0].element == Pos.ACTIVITIES_BTN) { ++ connectCorner(this.panel._leftCorner, this.statusArea.activities); ++ } ++ ++ if (visibleElements[visibleElements.length - 1].element == Pos.SYSTEM_MENU) { ++ connectCorner(this.panel._rightCorner, this.statusArea.aggregateMenu); ++ } ++ } ++ ++ this.panel.actor.hide(); ++ this.panel.actor.show(); ++ }, ++ ++ _updateGroupedElements: function(panelPositions) { ++ let previousPosition = 0; ++ let previousCenteredPosition = 0; ++ let currentGroup = -1; ++ ++ this._elementGroups = []; ++ ++ panelPositions.forEach(pos => { ++ let allocationMap = this.allocationMap[pos.element]; ++ ++ if (allocationMap.actor) { ++ allocationMap.actor.visible = pos.visible; ++ ++ if (!pos.visible) { ++ return; ++ } ++ ++ let currentPosition = pos.position; ++ let isCentered = Pos.checkIfCentered(currentPosition); ++ ++ if (currentPosition == Pos.STACKED_TL && previousPosition == Pos.STACKED_BR) { ++ currentPosition = Pos.STACKED_BR; ++ } ++ ++ if (!previousPosition || ++ (previousPosition == Pos.STACKED_TL && currentPosition != Pos.STACKED_TL) || ++ (previousPosition != Pos.STACKED_BR && currentPosition == Pos.STACKED_BR) || ++ (isCentered && previousPosition != currentPosition && previousPosition != Pos.STACKED_BR)) { ++ this._elementGroups[++currentGroup] = { elements: [], index: this._elementGroups.length, expandableIndex: -1 }; ++ previousCenteredPosition = 0; ++ } ++ ++ if (pos.element == Pos.TASKBAR) { ++ this._elementGroups[currentGroup].expandableIndex = this._elementGroups[currentGroup].elements.length; ++ } ++ ++ if (isCentered && !this._elementGroups[currentGroup].isCentered) { ++ this._elementGroups[currentGroup].isCentered = 1; ++ previousCenteredPosition = currentPosition; ++ } ++ ++ this._elementGroups[currentGroup].position = previousCenteredPosition || currentPosition; ++ this._elementGroups[currentGroup].elements.push(allocationMap); ++ ++ allocationMap.position = currentPosition; ++ previousPosition = currentPosition; ++ } ++ }); ++ }, ++ ++ _disablePanelCornerSignals: function() { ++ if (this.panel._rightCorner && this.panel._rightCorner._buttonStyleChangedSignalId) { ++ this.panel._rightCorner._button.disconnect(this.panel._rightCorner._buttonStyleChangedSignalId); ++ delete this.panel._rightCorner._buttonStyleChangedSignalId; ++ } ++ ++ if (this.panel._leftCorner && this.panel._leftCorner._buttonStyleChangedSignalId) { ++ this.panel._leftCorner._button.disconnect(this.panel._leftCorner._buttonStyleChangedSignalId); ++ delete this.panel._leftCorner._buttonStyleChangedSignalId; ++ } ++ }, ++ ++ _bindSettingsChanges: function() { ++ let isVertical = this.checkIfVertical(); ++ ++ this._signalsHandler.add( ++ [ ++ Me.settings, ++ [ ++ 'changed::panel-sizes', ++ 'changed::group-apps' ++ ], ++ () => this._resetGeometry() ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::appicon-margin', ++ 'changed::appicon-padding' ++ ], ++ () => this.taskbar.resetAppIcons() ++ ], ++ [ ++ Me.settings, ++ 'changed::show-appmenu', ++ () => this._setAppmenuVisible(Me.settings.get_boolean('show-appmenu')) ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::showdesktop-button-width', ++ 'changed::trans-use-custom-bg', ++ 'changed::desktop-line-use-custom-color', ++ 'changed::desktop-line-custom-color', ++ 'changed::trans-bg-color' ++ ], ++ () => this._setShowDesktopButtonStyle() ++ ], ++ [ ++ Me.desktopSettings, ++ 'changed::clock-format', ++ () => { ++ this._clockFormat = null; ++ ++ if (isVertical) { ++ this._formatVerticalClock(); ++ } ++ } ++ ], ++ [ ++ Me.settings, ++ 'changed::progress-show-bar', ++ () => this._initProgressManager() ++ ], ++ [ ++ Me.settings, ++ 'changed::progress-show-count', ++ () => this._initProgressManager() ++ ] ++ ); ++ ++ if (isVertical) { ++ this._signalsHandler.add([Me.settings, 'changed::group-apps-label-max-width', () => this._resetGeometry()]); ++ } ++ }, ++ ++ _setPanelMenu: function(propName, constr, container) { ++ if (!this.statusArea[propName]) { ++ this.statusArea[propName] = this._getPanelMenu(propName, constr); ++ this.menuManager.addMenu(this.statusArea[propName].menu); ++ container.insert_child_at_index(this.statusArea[propName].container, 0); ++ } ++ }, ++ ++ _removePanelMenu: function(propName) { ++ if (this.statusArea[propName]) { ++ let parent = this.statusArea[propName].container.get_parent(); ++ ++ if (parent) { ++ parent.remove_actor(this.statusArea[propName].container); ++ } ++ ++ //calling this.statusArea[propName].destroy(); is buggy for now, gnome-shell never ++ //destroys those panel menus... ++ //since we can't destroy the menu (hence properly disconnect its signals), let's ++ //store it so the next time a panel needs one of its kind, we can reuse it instead ++ //of creating a new one ++ let panelMenu = this.statusArea[propName]; ++ ++ this.menuManager.removeMenu(panelMenu.menu); ++ Me.persistentStorage[propName].push(panelMenu); ++ this.statusArea[propName] = null; ++ } ++ }, ++ ++ _getPanelMenu: function(propName, constr) { ++ Me.persistentStorage[propName] = Me.persistentStorage[propName] || []; ++ ++ if (!Me.persistentStorage[propName].length) { ++ Me.persistentStorage[propName].push(new constr()); ++ } ++ ++ return Me.persistentStorage[propName].pop(); ++ }, ++ ++ _setPanelGhostSize: function() { ++ this._myPanelGhost.set_size(this.width, this.checkIfVertical() ? 1 : this.height); ++ }, ++ ++ _setSearchEntryOffset: function(offset) { ++ if (this.isPrimary) { ++ //In the overview, when the panel is vertical the search-entry is the only element ++ //that doesn't natively take into account the size of a side dock, as it is always ++ //centered relatively to the monitor. This looks misaligned, adjust it here so it ++ //is centered like the rest of the overview elements. ++ let paddingSide = this.getPosition() == St.Side.LEFT ? 'left' : 'right'; ++ let scaleFactor = Utils.getScaleFactor(); ++ let style = offset ? 'padding-' + paddingSide + ':' + (offset / scaleFactor) + 'px;' : null; ++ let searchEntry = Main.overview._searchEntry || Main.overview._overview._searchEntry; ++ ++ searchEntry.get_parent().set_style(style); ++ } ++ }, ++ ++ _adjustForOverview: function() { ++ let isFocusedMonitor = this.panelManager.checkIfFocusedMonitor(this.monitor); ++ let isOverview = !!Main.overview.visibleTarget; ++ let isOverviewFocusedMonitor = isOverview && isFocusedMonitor; ++ let isShown = !isOverview || isOverviewFocusedMonitor; ++ ++ this.panelBox[isShown ? 'show' : 'hide'](); ++ ++ if (isOverview) { ++ this._myPanelGhost[isOverviewFocusedMonitor ? 'show' : 'hide'](); ++ ++ if (isOverviewFocusedMonitor) { ++ Utils.getPanelGhost().set_size(1, this.geom.position == St.Side.TOP ? 0 : 32); ++ } ++ } ++ }, ++ ++ _resetGeometry: function() { ++ this.geom = this.getGeometry(); ++ this._setPanelGhostSize(); ++ this._setPanelPosition(); ++ this.taskbar.resetAppIcons(true); ++ this.dynamicTransparency.updateExternalStyle(); ++ ++ if (this.intellihide && this.intellihide.enabled) { ++ this.intellihide.reset(); ++ } ++ ++ if (this.checkIfVertical()) { ++ this.showAppsIconWrapper.realShowAppsIcon.toggleButton.set_width(this.geom.w); ++ this._refreshVerticalAlloc(); ++ this._setSearchEntryOffset(this.geom.w); ++ } ++ }, ++ ++ getGeometry: function() { ++ let scaleFactor = Utils.getScaleFactor(); ++ let panelBoxTheme = this.panelBox.get_theme_node(); ++ let lrPadding = panelBoxTheme.get_padding(St.Side.RIGHT) + panelBoxTheme.get_padding(St.Side.LEFT); ++ let topPadding = panelBoxTheme.get_padding(St.Side.TOP); ++ let tbPadding = topPadding + panelBoxTheme.get_padding(St.Side.BOTTOM); ++ let position = this.getPosition(); ++ let length = PanelSettings.getPanelLength(Me.settings, this.monitor.index) / 100; ++ let anchor = PanelSettings.getPanelAnchor(Me.settings, this.monitor.index); ++ let anchorPlaceOnMonitor = 0; ++ let gsTopPanelOffset = 0; ++ let x = 0, y = 0; ++ let w = 0, h = 0; ++ ++ const panelSize = PanelSettings.getPanelSize(Me.settings, this.monitor.index); ++ this.dtpSize = panelSize * scaleFactor; ++ ++ if (Me.settings.get_boolean('stockgs-keep-top-panel') && Main.layoutManager.primaryMonitor == this.monitor) { ++ gsTopPanelOffset = Main.layoutManager.panelBox.height - topPadding; ++ } ++ ++ if (this.checkIfVertical()) { ++ if (!Me.settings.get_boolean('group-apps')) { ++ // add window title width and side padding of _dtpIconContainer when vertical ++ this.dtpSize += Me.settings.get_int('group-apps-label-max-width') + AppIcons.DEFAULT_PADDING_SIZE * 2 / scaleFactor; ++ } ++ ++ this.sizeFunc = 'get_preferred_height', ++ this.fixedCoord = { c1: 'x1', c2: 'x2' }, ++ this.varCoord = { c1: 'y1', c2: 'y2' }; ++ ++ w = this.dtpSize; ++ h = this.monitor.height * length - tbPadding - gsTopPanelOffset; ++ } else { ++ this.sizeFunc = 'get_preferred_width'; ++ this.fixedCoord = { c1: 'y1', c2: 'y2' }; ++ this.varCoord = { c1: 'x1', c2: 'x2' }; ++ ++ w = this.monitor.width * length - lrPadding; ++ h = this.dtpSize; ++ } ++ ++ if (position == St.Side.TOP || position == St.Side.LEFT) { ++ x = this.monitor.x; ++ y = this.monitor.y + gsTopPanelOffset; ++ } else if (position == St.Side.RIGHT) { ++ x = this.monitor.x + this.monitor.width - this.dtpSize - lrPadding; ++ y = this.monitor.y + gsTopPanelOffset; ++ } else { //BOTTOM ++ x = this.monitor.x; ++ y = this.monitor.y + this.monitor.height - this.dtpSize - tbPadding; ++ } ++ ++ if (this.checkIfVertical()) { ++ if (anchor === Pos.MIDDLE) { ++ anchorPlaceOnMonitor = (this.monitor.height - h) / 2; ++ } else if (anchor === Pos.END) { ++ anchorPlaceOnMonitor = this.monitor.height - h; ++ } else { // Pos.START ++ anchorPlaceOnMonitor = 0; ++ } ++ y = y + anchorPlaceOnMonitor; ++ } else { ++ if (anchor === Pos.MIDDLE) { ++ anchorPlaceOnMonitor = (this.monitor.width - w) / 2; ++ } else if (anchor === Pos.END) { ++ anchorPlaceOnMonitor = this.monitor.width - w; ++ } else { // Pos.START ++ anchorPlaceOnMonitor = 0; ++ } ++ x = x + anchorPlaceOnMonitor; ++ } ++ ++ return { ++ x: x, y: y, ++ w: w, h: h, ++ lrPadding: lrPadding, ++ tbPadding: tbPadding, ++ position: position ++ }; ++ }, ++ ++ _setAllocationMap: function() { ++ this.allocationMap = {}; ++ let setMap = (name, actor, isBox) => this.allocationMap[name] = { ++ actor: actor, ++ isBox: isBox || 0, ++ box: new Clutter.ActorBox() ++ }; ++ ++ setMap(Pos.SHOW_APPS_BTN, this.showAppsIconWrapper.realShowAppsIcon); ++ setMap(Pos.ACTIVITIES_BTN, this.statusArea.activities ? this.statusArea.activities.container : 0); ++ setMap(Pos.LEFT_BOX, this._leftBox, 1); ++ setMap(Pos.TASKBAR, this.taskbar.actor); ++ setMap(Pos.CENTER_BOX, this._centerBox, 1); ++ setMap(Pos.DATE_MENU, this.statusArea.dateMenu.container); ++ setMap(Pos.SYSTEM_MENU, this.statusArea.aggregateMenu.container); ++ setMap(Pos.RIGHT_BOX, this._rightBox, 1); ++ setMap(Pos.DESKTOP_BTN, this._showDesktopButton); ++ }, ++ ++ _mainPanelAllocate: function(actor, box, flags) { ++ Utils.setAllocation(this.panel.actor, box, flags); ++ }, ++ ++ vfunc_allocate: function(box, flags) { ++ Utils.setAllocation(this, box, flags); ++ ++ let fixed = 0; ++ let centeredMonitorGroup; ++ let panelAlloc = new Clutter.ActorBox({ x1: 0, y1: 0, x2: this.geom.w, y2: this.geom.h }); ++ let assignGroupSize = (group, update) => { ++ group.size = 0; ++ group.tlOffset = 0; ++ group.brOffset = 0; ++ ++ group.elements.forEach(element => { ++ if (!update) { ++ element.box[this.fixedCoord.c1] = panelAlloc[this.fixedCoord.c1]; ++ element.box[this.fixedCoord.c2] = panelAlloc[this.fixedCoord.c2]; ++ element.natSize = element.actor[this.sizeFunc](-1)[1]; ++ } ++ ++ if (!group.isCentered || Pos.checkIfCentered(element.position)) { ++ group.size += element.natSize; ++ } else if (element.position == Pos.STACKED_TL) {  ++ group.tlOffset += element.natSize; ++ } else { // Pos.STACKED_BR ++ group.brOffset += element.natSize; ++ } ++ }); ++ ++ if (group.isCentered) { ++ group.size += Math.max(group.tlOffset, group.brOffset) * 2; ++ group.tlOffset = Math.max(group.tlOffset - group.brOffset, 0); ++ } ++ }; ++ let allocateGroup = (group, tlLimit, brLimit) => { ++ let startPosition = tlLimit; ++ let currentPosition = 0; ++ ++ if (group.expandableIndex >= 0) { ++ let availableSize = brLimit - tlLimit; ++ let expandable = group.elements[group.expandableIndex]; ++ let i = 0; ++ let l = this._elementGroups.length; ++ let tlSize = 0; ++ let brSize = 0; ++ ++ if (centeredMonitorGroup && (centeredMonitorGroup != group || expandable.position != Pos.CENTERED_MONITOR)) { ++ if (centeredMonitorGroup.index < group.index || (centeredMonitorGroup == group && expandable.position == Pos.STACKED_TL)) { ++ i = centeredMonitorGroup.index; ++ } else { ++ l = centeredMonitorGroup.index; ++ } ++ } ++ ++ for (; i < l; ++i) { ++ let refGroup = this._elementGroups[i]; ++ ++ if (i < group.index && (!refGroup.fixed || refGroup[this.varCoord.c2] > tlLimit)) { ++ tlSize += refGroup.size; ++ } else if (i > group.index && (!refGroup.fixed || refGroup[this.varCoord.c1] < brLimit)) { ++ brSize += refGroup.size; ++ } ++ } ++ ++ if (group.isCentered) { ++ availableSize -= Math.max(tlSize, brSize) * 2; ++ } else { ++ availableSize -= tlSize + brSize; ++ } ++ ++ if (availableSize < group.size) { ++ expandable.natSize -= (group.size - availableSize) * (group.isCentered && !Pos.checkIfCentered(expandable.position) ? .5 : 1); ++ assignGroupSize(group, true); ++ } ++ } ++ ++ if (group.isCentered) { ++ startPosition = tlLimit + (brLimit - tlLimit - group.size) * .5; ++ } else if (group.position == Pos.STACKED_BR) { ++ startPosition = brLimit - group.size; ++ } ++ ++ currentPosition = group.tlOffset + startPosition; ++ ++ group.elements.forEach(element => { ++ element.box[this.varCoord.c1] = Math.round(currentPosition); ++ element.box[this.varCoord.c2] = Math.round((currentPosition += element.natSize)); ++ ++ if (element.isBox) { ++ return element.actor.allocate(element.box, flags, true); ++ } ++ ++ Utils.allocate(element.actor, element.box, flags, false); ++ }); ++ ++ group[this.varCoord.c1] = startPosition; ++ group[this.varCoord.c2] = currentPosition; ++ group.fixed = 1; ++ ++fixed; ++ }; ++ ++ Utils.allocate(this.panel.actor, panelAlloc, flags); ++ ++ this._elementGroups.forEach(group => { ++ group.fixed = 0; ++ ++ assignGroupSize(group); ++ ++ if (group.position == Pos.CENTERED_MONITOR) { ++ centeredMonitorGroup = group; ++ } ++ }); ++ ++ if (centeredMonitorGroup) { ++ allocateGroup(centeredMonitorGroup, panelAlloc[this.varCoord.c1], panelAlloc[this.varCoord.c2]); ++ } ++ ++ let iterations = 0; //failsafe ++ while (fixed < this._elementGroups.length && ++iterations < 10) { ++ for (let i = 0, l = this._elementGroups.length; i < l; ++i) { ++ let group = this._elementGroups[i]; ++ ++ if (group.fixed) { ++ continue; ++ } ++ ++ let prevGroup = this._elementGroups[i - 1]; ++ let nextGroup = this._elementGroups[i + 1]; ++ let prevLimit = prevGroup && prevGroup.fixed ? prevGroup[this.varCoord.c2] : ++ centeredMonitorGroup && group.index > centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c2] : panelAlloc[this.varCoord.c1]; ++ let nextLimit = nextGroup && nextGroup.fixed ? nextGroup[this.varCoord.c1] : ++ centeredMonitorGroup && group.index < centeredMonitorGroup.index ? centeredMonitorGroup[this.varCoord.c1] : panelAlloc[this.varCoord.c2]; ++ ++ if (group.position == Pos.STACKED_TL) { ++ allocateGroup(group, panelAlloc[this.varCoord.c1], nextLimit); ++ } else if (group.position == Pos.STACKED_BR) { ++ allocateGroup(group, prevLimit, panelAlloc[this.varCoord.c2]); ++ } else if ((!prevGroup || prevGroup.fixed) && (!nextGroup || nextGroup.fixed)) { // CENTERED ++ allocateGroup(group, prevLimit, nextLimit); ++ } ++ } ++ } ++ ++ if (this.geom.position == St.Side.TOP) { ++ let childBoxLeftCorner = new Clutter.ActorBox(); ++ let childBoxRightCorner = new Clutter.ActorBox(); ++ let currentCornerSize = this.cornerSize; ++ let panelAllocFixedSize = box[this.fixedCoord.c2] - box[this.fixedCoord.c1]; ++ ++ [ , this.cornerSize] = this.panel._leftCorner.actor[this.sizeFunc](-1); ++ childBoxLeftCorner[this.varCoord.c1] = 0; ++ childBoxLeftCorner[this.varCoord.c2] = this.cornerSize; ++ childBoxLeftCorner[this.fixedCoord.c1] = panelAllocFixedSize; ++ childBoxLeftCorner[this.fixedCoord.c2] = panelAllocFixedSize + this.cornerSize; ++ ++ childBoxRightCorner[this.varCoord.c1] = box[this.varCoord.c2] - this.cornerSize; ++ childBoxRightCorner[this.varCoord.c2] = box[this.varCoord.c2]; ++ childBoxRightCorner[this.fixedCoord.c1] = panelAllocFixedSize; ++ childBoxRightCorner[this.fixedCoord.c2] = panelAllocFixedSize + this.cornerSize; ++ ++ Utils.allocate(this.panel._leftCorner.actor, childBoxLeftCorner, flags); ++ Utils.allocate(this.panel._rightCorner.actor, childBoxRightCorner, flags); ++ ++ if (this.cornerSize != currentCornerSize) { ++ this._setPanelClip(); ++ } ++ } ++ }, ++ ++ _setPanelPosition: function() { ++ let clipContainer = this.panelBox.get_parent(); ++ ++ this.set_size(this.geom.w, this.geom.h); ++ clipContainer.set_position(this.geom.x, this.geom.y); ++ ++ this._setVertical(this.panel.actor, this.checkIfVertical()); ++ ++ // styles for theming ++ Object.keys(St.Side).forEach(p => { ++ let cssName = 'dashtopanel' + p.charAt(0) + p.slice(1).toLowerCase(); ++ ++ this.panel.actor[(St.Side[p] == this.geom.position ? 'add' : 'remove') + '_style_class_name'](cssName); ++ }); ++ ++ this._setPanelClip(clipContainer); ++ ++ Main.layoutManager._updateHotCorners(); ++ Main.layoutManager._updatePanelBarrier(this); ++ }, ++ ++ _setPanelClip: function(clipContainer) { ++ clipContainer = clipContainer || this.panelBox.get_parent(); ++ this._timeoutsHandler.add([T7, 0, () => Utils.setClip(clipContainer, clipContainer.x, clipContainer.y, this.panelBox.width, this.panelBox.height + this.cornerSize)]); ++ }, ++ ++ _onButtonPress: function(actor, event) { ++ let type = event.type(); ++ let isPress = type == Clutter.EventType.BUTTON_PRESS; ++ let button = isPress ? event.get_button() : -1; ++ let [stageX, stageY] = event.get_coords(); ++ ++ if (button == 3 && global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, stageX, stageY) == this.panel.actor) { ++ //right click on an empty part of the panel, temporarily borrow and display the showapps context menu ++ Main.layoutManager.setDummyCursorGeometry(stageX, stageY, 0, 0); ++ ++ this.showAppsIconWrapper.createMenu(); ++ this.showAppsIconWrapper._menu.sourceActor = Main.layoutManager.dummyCursor; ++ this.showAppsIconWrapper.popupMenu(); ++ ++ return Clutter.EVENT_STOP; ++ } else if (Main.modalCount > 0 || event.get_source() != actor || ++ (!isPress && type != Clutter.EventType.TOUCH_BEGIN) || ++ (isPress && button != 1)) { ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ let params = this.checkIfVertical() ? [stageY, 'y', 'height'] : [stageX, 'x', 'width']; ++ let dragWindow = this._getDraggableWindowForPosition.apply(this, params.concat(['maximized_' + this.getOrientation() + 'ly'])); ++ ++ if (!dragWindow) ++ return Clutter.EVENT_PROPAGATE; ++ ++ global.display.begin_grab_op(dragWindow, ++ Meta.GrabOp.MOVING, ++ false, /* pointer grab */ ++ true, /* frame action */ ++ button, ++ event.get_state(), ++ event.get_time(), ++ stageX, stageY); ++ ++ return Clutter.EVENT_STOP; ++ }, ++ ++ _getDraggableWindowForPosition: function(stageCoord, coord, dimension, maximizedProp) { ++ let workspace = Utils.getCurrentWorkspace(); ++ let allWindowsByStacking = global.display.sort_windows_by_stacking( ++ workspace.list_windows() ++ ).reverse(); ++ ++ return Utils.find(allWindowsByStacking, metaWindow => { ++ let rect = metaWindow.get_frame_rect(); ++ ++ return metaWindow.get_monitor() == this.monitor.index && ++ metaWindow.showing_on_its_workspace() && ++ metaWindow.get_window_type() != Meta.WindowType.DESKTOP && ++ metaWindow[maximizedProp] && ++ stageCoord > rect[coord] && stageCoord < rect[coord] + rect[dimension]; ++ }); ++ }, ++ ++ _onBoxActorAdded: function(box) { ++ if (this.checkIfVertical()) { ++ this._setVertical(box, true); ++ } ++ }, ++ ++ _refreshVerticalAlloc: function() { ++ this._setVertical(this._centerBox, true); ++ this._setVertical(this._rightBox, true); ++ this._formatVerticalClock(); ++ }, ++ ++ _setVertical: function(actor, isVertical) { ++ let _set = (actor, isVertical) => { ++ if (!actor || actor instanceof Dash.DashItemContainer || actor instanceof Taskbar.TaskbarItemContainer) { ++ return; ++ } ++ ++ if (actor instanceof St.BoxLayout) { ++ actor.vertical = isVertical; ++ } else if ((actor._delegate || actor) instanceof PanelMenu.ButtonBox && actor != this.statusArea.appMenu) { ++ let child = actor.get_first_child(); ++ ++ if (isVertical && !actor.visible && !actor._dtpVisibleId) { ++ this._unmappedButtons.push(actor); ++ actor._dtpVisibleId = actor.connect('notify::visible', () => { ++ this._disconnectVisibleId(actor); ++ this._refreshVerticalAlloc(); ++ }); ++ actor._dtpDestroyId = actor.connect('destroy', () => this._disconnectVisibleId(actor)); ++ } ++ ++ if (child) { ++ let [, natWidth] = actor.get_preferred_width(-1); ++ ++ child.x_align = Clutter.ActorAlign[isVertical ? 'CENTER' : 'START']; ++ actor.set_width(isVertical ? this.dtpSize : -1); ++ isVertical = isVertical && (natWidth > this.dtpSize); ++ actor[(isVertical ? 'add' : 'remove') + '_style_class_name']('vertical'); ++ } ++ } ++ ++ actor.get_children().forEach(c => _set(c, isVertical)); ++ }; ++ ++ _set(actor, false); ++ _set(actor, isVertical); ++ }, ++ ++ _disconnectVisibleId: function(actor) { ++ actor.disconnect(actor._dtpVisibleId); ++ actor.disconnect(actor._dtpDestroyId); ++ ++ delete actor._dtpVisibleId; ++ delete actor._dtpDestroyId; ++ ++ this._unmappedButtons.splice(this._unmappedButtons.indexOf(actor), 1); ++ }, ++ ++ _setAppmenuVisible: function(isVisible) { ++ let parent; ++ let appMenu = this.statusArea.appMenu; ++ ++ if(appMenu) ++ parent = appMenu.container.get_parent(); ++ ++ if (parent) { ++ parent.remove_child(appMenu.container); ++ } ++ ++ if (isVisible && appMenu) { ++ this._leftBox.insert_child_above(appMenu.container, null); ++ } ++ }, ++ ++ _formatVerticalClock: function() { ++ // https://github.com/GNOME/gnome-desktop/blob/master/libgnome-desktop/gnome-wall-clock.c#L310 ++ if (this.statusArea.dateMenu) { ++ let datetime = this.statusArea.dateMenu._clock.clock; ++ let datetimeParts = datetime.split(' '); ++ let time = datetimeParts[1]; ++ let clockText = this.statusArea.dateMenu._clockDisplay.clutter_text; ++ let setClockText = text => { ++ let stacks = text instanceof Array; ++ let separator = '\n‧‧\n'; ++ ++ clockText.set_text((stacks ? text.join(separator) : text).trim()); ++ clockText.set_use_markup(stacks); ++ clockText.get_allocation_box(); ++ ++ return !clockText.get_layout().is_ellipsized(); ++ }; ++ ++ if (clockText.ellipsize == Pango.EllipsizeMode.NONE) { ++ //on gnome-shell 3.36.4, the clockdisplay isn't ellipsize anymore, so set it back ++ clockText.ellipsize = Pango.EllipsizeMode.END; ++ } ++ ++ if (!time) { ++ datetimeParts = datetime.split(' '); ++ time = datetimeParts.pop(); ++ datetimeParts = [datetimeParts.join(' '), time]; ++ } ++ ++ if (!setClockText(datetime) && ++ !setClockText(datetimeParts) && ++ !setClockText(time)) { ++ let timeParts = time.split('∶'); ++ ++ if (!this._clockFormat) { ++ this._clockFormat = Me.desktopSettings.get_string('clock-format'); ++ } ++ ++ if (this._clockFormat == '12h') { ++ timeParts.push.apply(timeParts, timeParts.pop().split(' ')); ++ } ++ ++ setClockText(timeParts); ++ } ++ } ++ }, ++ ++ _setShowDesktopButton: function (add) { ++ if (add) { ++ if(this._showDesktopButton) ++ return; ++ ++ this._showDesktopButton = new St.Bin({ style_class: 'showdesktop-button', ++ reactive: true, ++ can_focus: true, ++ // x_fill: true, ++ // y_fill: true, ++ track_hover: true }); ++ ++ this._setShowDesktopButtonStyle(); ++ ++ this._showDesktopButton.connect('button-press-event', () => this._onShowDesktopButtonPress()); ++ this._showDesktopButton.connect('enter-event', () => { ++ this._showDesktopButton.add_style_class_name(this._getBackgroundBrightness() ? ++ 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered'); ++ ++ if (Me.settings.get_boolean('show-showdesktop-hover')) { ++ this._timeoutsHandler.add([T4, Me.settings.get_int('show-showdesktop-delay'), () => { ++ this._hiddenDesktopWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++ this._toggleWorkspaceWindows(true, this._hiddenDesktopWorkspace); ++ }]); ++ } ++ }); ++ ++ this._showDesktopButton.connect('leave-event', () => { ++ this._showDesktopButton.remove_style_class_name(this._getBackgroundBrightness() ? ++ 'showdesktop-button-light-hovered' : 'showdesktop-button-dark-hovered'); ++ ++ if (Me.settings.get_boolean('show-showdesktop-hover')) { ++ if (this._timeoutsHandler.getId(T4)) { ++ this._timeoutsHandler.remove(T4); ++ } else if (this._hiddenDesktopWorkspace) { ++ this._toggleWorkspaceWindows(false, this._hiddenDesktopWorkspace); ++ } ++  } ++ }); ++ ++ this.panel.actor.add_child(this._showDesktopButton); ++ } else { ++ if(!this._showDesktopButton) ++ return; ++ ++ this.panel.actor.remove_child(this._showDesktopButton); ++ this._showDesktopButton.destroy(); ++ this._showDesktopButton = null; ++ } ++ }, ++ ++ _setShowDesktopButtonStyle: function() { ++ let rgb = this._getBackgroundBrightness() ? "rgba(55, 55, 55, .2)" : "rgba(200, 200, 200, .2)"; ++ ++ let isLineCustom = Me.settings.get_boolean('desktop-line-use-custom-color'); ++ rgb = isLineCustom ? Me.settings.get_string('desktop-line-custom-color') : rgb; ++ ++ if (this._showDesktopButton) { ++ let buttonSize = Me.settings.get_int('showdesktop-button-width') + 'px;'; ++ let isVertical = this.checkIfVertical(); ++ ++ let sytle = "border: 0 solid " + rgb + ";"; ++ sytle += isVertical ? 'border-top-width:1px;height:' + buttonSize : 'border-left-width:1px;width:' + buttonSize; ++ ++ this._showDesktopButton.set_style(sytle); ++ this._showDesktopButton[(isVertical ? 'x' : 'y') + '_expand'] = true; ++ } ++ }, ++ ++ // _getBackgroundBrightness: return true if panel has a bright background color ++ _getBackgroundBrightness: function() { ++ return Utils.checkIfColorIsBright(this.dynamicTransparency.backgroundColorRgb); ++ }, ++ ++ _toggleWorkspaceWindows: function(hide, workspace) { ++ let time = Me.settings.get_int('show-showdesktop-time') * .001; ++ ++ workspace.list_windows().forEach(w => { ++ if (!w.minimized) { ++ let tweenOpts = { ++ opacity: hide ? 0 : 255, ++ time: time, ++ transition: 'easeOutQuad' ++ }; ++ ++ Utils.animateWindowOpacity(w.get_compositor_private(), tweenOpts); ++ } ++ }); ++ }, ++ ++ _onShowDesktopButtonPress: function() { ++ let label = 'trackerFocusApp'; ++ ++ this._signalsHandler.removeWithLabel(label); ++ this._timeoutsHandler.remove(T5); ++ ++ if(this._restoreWindowList && this._restoreWindowList.length) { ++ this._timeoutsHandler.remove(T4); ++ ++ let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++ let windows = current_workspace.list_windows(); ++ this._restoreWindowList.forEach(function(w) { ++ if(windows.indexOf(w) > -1) ++ Main.activateWindow(w); ++ }); ++ this._restoreWindowList = null; ++ } else { ++ let current_workspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++ let windows = current_workspace.list_windows().filter(function (w) { ++ return w.showing_on_its_workspace() && !w.skip_taskbar; ++ }); ++ windows = global.display.sort_windows_by_stacking(windows); ++ ++ windows.forEach(function(w) { ++ w.minimize(); ++ }); ++ ++ this._restoreWindowList = windows; ++ ++ this._timeoutsHandler.add([T5, 20, () => this._signalsHandler.addWithLabel( ++ label, ++ [ ++ tracker, ++ 'notify::focus-app', ++ () => this._restoreWindowList = null ++ ] ++ )]); ++ } ++ ++ Main.overview.hide(); ++ }, ++ ++ _onPanelMouseScroll: function(actor, event) { ++ let scrollAction = Me.settings.get_string('scroll-panel-action'); ++ let direction = Utils.getMouseScrollDirection(event); ++ ++ if (!this._checkIfIgnoredScrollSource(event.get_source()) && !this._timeoutsHandler.getId(T6)) { ++ if (direction && scrollAction === 'SWITCH_WORKSPACE') { ++ let args = [global.display]; ++ ++ //adjust for horizontal workspaces ++ if (Utils.DisplayWrapper.getWorkspaceManager().layout_rows === 1) { ++ direction = direction == 'up' ? 'left' : 'right'; ++ } ++ ++ //gnome-shell < 3.30 needs an additional "screen" param ++ global.screen ? args.push(global.screen) : 0; ++ ++ let showWsPopup = Me.settings.get_boolean('scroll-panel-show-ws-popup'); ++ showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = { display: () => {} }; ++ Main.wm._showWorkspaceSwitcher.apply(Main.wm, args.concat([0, { get_name: () => 'switch---' + direction }])); ++ showWsPopup ? 0 : Main.wm._workspaceSwitcherPopup = null; ++ } else if (direction && scrollAction === 'CYCLE_WINDOWS') { ++ let windows = this.taskbar.getAppInfos().reduce((ws, appInfo) => ws.concat(appInfo.windows), []); ++ ++ Utils.activateSiblingWindow(windows, direction); ++ } else if (scrollAction === 'CHANGE_VOLUME' && !event.is_pointer_emulated()) { ++ var proto = Volume.Indicator.prototype; ++ var func = proto.vfunc_scroll_event || proto._onScrollEvent; ++ ++ func.call(Main.panel.statusArea.aggregateMenu._volume, 0, event); ++ } else { ++ return; ++ } ++ ++ var scrollDelay = Me.settings.get_int('scroll-panel-delay'); ++ ++ if (scrollDelay) { ++ this._timeoutsHandler.add([T6, scrollDelay, () => {}]); ++ } ++ } ++ }, ++ ++ _checkIfIgnoredScrollSource: function(source) { ++ let ignoredConstr = ['WorkspaceIndicator']; ++ ++ return source._dtpIgnoreScroll || ignoredConstr.indexOf(source.constructor.name) >= 0; ++ }, ++ ++ _initProgressManager: function() { ++ if(!this.progressManager && (Me.settings.get_boolean('progress-show-bar') || Me.settings.get_boolean('progress-show-count'))) ++ this.progressManager = new Progress.ProgressManager(); ++ }, ++}); ++ ++var dtpSecondaryPanel = Utils.defineClass({ ++ Name: 'DashToPanel-SecondaryPanel', ++ Extends: St.Widget, ++ ++ _init: function(params) { ++ this.callParent('_init', params); ++ }, ++ ++ vfunc_allocate: function(box, flags) { ++ Utils.setAllocation(this, box, flags); ++ } ++}); ++ ++var dtpSecondaryAggregateMenu = Utils.defineClass({ ++ Name: 'DashToPanel-SecondaryAggregateMenu', ++ Extends: PanelMenu.Button, ++ ++ _init: function() { ++ this.callParent('_init', 0.0, C_("System menu in the top bar", "System"), false); ++ ++ Utils.wrapActor(this); ++ ++ this.menu.actor.add_style_class_name('aggregate-menu'); ++ ++ let menuLayout = new Panel.AggregateLayout(); ++ this.menu.box.set_layout_manager(menuLayout); ++ ++ this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' }); ++ this.actor.add_child(this._indicators); ++ ++ this._power = new imports.ui.status.power.Indicator(); ++ this._volume = new imports.ui.status.volume.Indicator(); ++ this._brightness = new imports.ui.status.brightness.Indicator(); ++ this._system = new imports.ui.status.system.Indicator(); ++ ++ if (Config.PACKAGE_VERSION >= '3.28') { ++ this._thunderbolt = new imports.ui.status.thunderbolt.Indicator(); ++ this._indicators.add_child(Utils.getIndicators(this._thunderbolt)); ++ } ++ ++ if (Config.PACKAGE_VERSION < '3.37') { ++ this._screencast = new imports.ui.status.screencast.Indicator(); ++ this._indicators.add_child(Utils.getIndicators(this._screencast)); ++ } ++ ++ if (Config.PACKAGE_VERSION >= '3.24') { ++ this._nightLight = new imports.ui.status.nightLight.Indicator(); ++ this._indicators.add_child(Utils.getIndicators(this._nightLight)); ++ } ++ ++ if (Config.HAVE_NETWORKMANAGER && Config.PACKAGE_VERSION >= '3.24') { ++ this._network = new imports.ui.status.network.NMApplet(); ++ this._indicators.add_child(Utils.getIndicators(this._network)); ++ } ++ ++ if (Config.HAVE_BLUETOOTH) { ++ this._bluetooth = new imports.ui.status.bluetooth.Indicator(); ++ this._indicators.add_child(Utils.getIndicators(this._bluetooth)); ++ } ++ ++ this._indicators.add_child(Utils.getIndicators(this._volume)); ++ this._indicators.add_child(Utils.getIndicators(this._power)); ++ this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); ++ ++ this.menu.addMenuItem(this._volume.menu); ++ this._volume._volumeMenu._readOutput(); ++ this._volume._volumeMenu._readInput(); ++ ++ this.menu.addMenuItem(this._brightness.menu); ++ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ ++ if (this._network) { ++ this.menu.addMenuItem(this._network.menu); ++ } ++ ++ if (this._bluetooth) { ++ this.menu.addMenuItem(this._bluetooth.menu); ++ } ++ ++ this.menu.addMenuItem(this._power.menu); ++ this._power._sync(); ++ ++ if (this._nightLight) { ++ this.menu.addMenuItem(this._nightLight.menu); ++ } ++ ++ this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); ++ this.menu.addMenuItem(this._system.menu); ++ ++ menuLayout.addSizeChild(this._power.menu.actor); ++ menuLayout.addSizeChild(this._system.menu.actor); ++ }, ++}); +diff --git a/extensions/dash-to-panel/panelManager.js b/extensions/dash-to-panel/panelManager.js +new file mode 100755 +index 00000000..20ee12d8 +--- /dev/null ++++ b/extensions/dash-to-panel/panelManager.js +@@ -0,0 +1,901 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * ++ * Code to re-anchor the panel was taken from Thoma5 BottomPanel: ++ * https://github.com/Thoma5/gnome-shell-extension-bottompanel ++ * ++ * Pattern for moving clock based on Frippery Move Clock by R M Yorston ++ * http://frippery.org/extensions/ ++ * ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Overview = Me.imports.overview; ++const Panel = Me.imports.panel; ++const PanelSettings = Me.imports.panelSettings; ++const Proximity = Me.imports.proximity; ++const Taskbar = Me.imports.taskbar; ++const Utils = Me.imports.utils; ++ ++const Config = imports.misc.config; ++const Lang = imports.lang; ++const Gi = imports._gi; ++const GLib = imports.gi.GLib; ++const Clutter = imports.gi.Clutter; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++ ++const AppDisplay = imports.ui.appDisplay; ++const BoxPointer = imports.ui.boxpointer; ++const Dash = imports.ui.dash; ++const IconGrid = imports.ui.iconGrid; ++const LookingGlass = imports.ui.lookingGlass; ++const Main = imports.ui.main; ++const PanelMenu = imports.ui.panelMenu; ++const Layout = imports.ui.layout; ++const WM = imports.ui.windowManager; ++const WorkspacesView = imports.ui.workspacesView; ++ ++var dtpPanelManager = Utils.defineClass({ ++ Name: 'DashToPanel.PanelManager', ++ ++ _init: function() { ++ this.overview = new Overview.dtpOverview(); ++ this.panelsElementPositions = {}; ++ ++ this._saveMonitors(); ++ ++ Utils.getAppDisplayViews().forEach(v => { ++ Utils.wrapActor(v.view); ++ Utils.wrapActor(v.view._grid); ++ }); ++ }, ++ ++ enable: function(reset) { ++ let dtpPrimaryIndex = Me.settings.get_int('primary-monitor'); ++ ++ this.dtpPrimaryMonitor = Main.layoutManager.monitors[dtpPrimaryIndex] || Main.layoutManager.primaryMonitor; ++ this.proximityManager = new Proximity.ProximityManager(); ++ ++ Utils.wrapActor(Main.panel); ++ Utils.wrapActor(Main.overview.dash || 0); ++ ++ this.primaryPanel = this._createPanel(this.dtpPrimaryMonitor, Me.settings.get_boolean('stockgs-keep-top-panel')); ++ this.allPanels = [ this.primaryPanel ]; ++ ++ this.overview.enable(this.primaryPanel); ++ ++ if (Me.settings.get_boolean('multi-monitors')) { ++ Main.layoutManager.monitors.filter(m => m != this.dtpPrimaryMonitor).forEach(m => { ++ this.allPanels.push(this._createPanel(m, true)); ++ }); ++ } ++ ++ global.dashToPanel.panels = this.allPanels; ++ global.dashToPanel.emit('panels-created'); ++ ++ this.allPanels.forEach(p => { ++ let panelPosition = p.getPosition(); ++ let leftOrRight = (panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT); ++ ++ p.panelBox.set_size( ++ leftOrRight ? -1 : p.geom.w + p.geom.lrPadding, ++ leftOrRight ? p.geom.h + p.geom.tbPadding : -1 ++ ); ++ ++ this._findPanelMenuButtons(p.panelBox).forEach(pmb => this._adjustPanelMenuButton(pmb, p.monitor, panelPosition)); ++ ++ p.taskbar.iconAnimator.start(); ++ }); ++ ++ //in 3.32, BoxPointer now inherits St.Widget ++ if (BoxPointer.BoxPointer.prototype.vfunc_get_preferred_height) { ++ let panelManager = this; ++ ++ Utils.hookVfunc(BoxPointer.BoxPointer.prototype, 'get_preferred_height', function(forWidth) { ++ let alloc = { min_size: 0, natural_size: 0 }; ++ ++ [alloc.min_size, alloc.natural_size] = this.vfunc_get_preferred_height(forWidth); ++ ++ return panelManager._getBoxPointerPreferredHeight(this, alloc); ++ }); ++ } ++ ++ this._updatePanelElementPositions(); ++ this.setFocusedMonitor(this.dtpPrimaryMonitor); ++ ++ if (this.primaryPanel.checkIfVertical()) { ++ Main.wm._getPositionForDirection = newGetPositionForDirection; ++ } ++ ++ if (reset) return; ++ ++ this._oldViewSelectorAnimateIn = Main.overview.viewSelector._animateIn; ++ Main.overview.viewSelector._animateIn = Lang.bind(this.primaryPanel, newViewSelectorAnimateIn); ++ this._oldViewSelectorAnimateOut = Main.overview.viewSelector._animateOut; ++ Main.overview.viewSelector._animateOut = Lang.bind(this.primaryPanel, newViewSelectorAnimateOut); ++ ++ if (Config.PACKAGE_VERSION > '3.35.1') { ++ this._oldDoSpringAnimation = AppDisplay.BaseAppView.prototype._doSpringAnimation; ++ AppDisplay.BaseAppView.prototype._doSpringAnimation = newDoSpringAnimation; ++ } ++ ++ this._oldUpdatePanelBarrier = Main.layoutManager._updatePanelBarrier; ++ Main.layoutManager._updatePanelBarrier = (panel) => { ++ let panelUpdates = panel ? [panel] : this.allPanels; ++ ++ panelUpdates.forEach(p => newUpdatePanelBarrier.call(Main.layoutManager, p)); ++ }; ++ Main.layoutManager._updatePanelBarrier(); ++ ++ this._oldUpdateHotCorners = Main.layoutManager._updateHotCorners; ++ Main.layoutManager._updateHotCorners = Lang.bind(Main.layoutManager, newUpdateHotCorners); ++ Main.layoutManager._updateHotCorners(); ++ ++ this._forceHotCornerId = Me.settings.connect('changed::stockgs-force-hotcorner', () => Main.layoutManager._updateHotCorners()); ++ ++ if (Main.layoutManager._interfaceSettings) { ++ this._enableHotCornersId = Main.layoutManager._interfaceSettings.connect('changed::enable-hot-corners', () => Main.layoutManager._updateHotCorners()); ++ } ++ ++ this._oldOverviewRelayout = Main.overview._relayout; ++ Main.overview._relayout = Lang.bind(Main.overview, this._newOverviewRelayout); ++ ++ this._oldUpdateWorkspacesViews = Main.overview.viewSelector._workspacesDisplay._updateWorkspacesViews; ++ Main.overview.viewSelector._workspacesDisplay._updateWorkspacesViews = Lang.bind(Main.overview.viewSelector._workspacesDisplay, this._newUpdateWorkspacesViews); ++ ++ this._oldGetShowAppsButton = Main.overview.getShowAppsButton; ++ Main.overview.getShowAppsButton = this._newGetShowAppsButton.bind(this); ++ ++ ++ // Since Gnome 3.8 dragging an app without having opened the overview before cause the attemp to ++ //animate a null target since some variables are not initialized when the viewSelector is created ++ if(Main.overview.viewSelector._activePage == null) ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._workspacesPage; ++ ++ LookingGlass.LookingGlass.prototype._oldResize = LookingGlass.LookingGlass.prototype._resize; ++ LookingGlass.LookingGlass.prototype._resize = _newLookingGlassResize; ++ ++ LookingGlass.LookingGlass.prototype._oldOpen = LookingGlass.LookingGlass.prototype.open; ++ LookingGlass.LookingGlass.prototype.open = _newLookingGlassOpen; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ if (Config.PACKAGE_VERSION > '3.35.9') { ++ let currentAppsView; ++ ++ this._oldAnimateIconPosition = IconGrid.animateIconPosition; ++ IconGrid.animateIconPosition = newAnimateIconPosition.bind(this); ++ ++ this._signalsHandler.add( ++ [ ++ Utils.DisplayWrapper.getScreen(), ++ 'window-entered-monitor', ++ () => this._needsIconAllocate = 1 ++ ] ++ ); ++ ++ Utils.getAppDisplayViews().forEach(v => { ++ if (!v.control || v.control.has_style_pseudo_class('checked')) { ++ currentAppsView = v; ++ } ++ ++ if (v.control) { ++ this._signalsHandler.add( ++ [ ++ v.control, ++ 'clicked', ++ () => { ++ this._needsIconAllocate = currentAppsView != v; ++ currentAppsView = v; ++ } ++ ] ++ ); ++ } ++ ++ this._signalsHandler.add( ++ [ ++ v.view, ++ 'notify::visible', ++ () => this._needsIconAllocate = !(currentAppsView != v && !v.view.visible) ++ ], ++ [ ++ v.view._grid, ++ 'animation-done', ++ () => this._needsIconAllocate = 0 ++ ] ++ ); ++ }); ++ } ++ ++ //listen settings ++ this._signalsHandler.add( ++ [ ++ Me.settings, ++ [ ++ 'changed::primary-monitor', ++ 'changed::multi-monitors', ++ 'changed::isolate-monitors', ++ 'changed::panel-positions', ++ 'changed::panel-lengths', ++ 'changed::panel-anchors', ++ 'changed::stockgs-keep-top-panel' ++ ], ++ () => this._reset() ++ ], ++ [ ++ Me.settings, ++ 'changed::panel-element-positions', ++ () => this._updatePanelElementPositions() ++ ], ++ [ ++ Me.settings, ++ 'changed::intellihide-key-toggle-text', ++ () => this._setKeyBindings(true) ++ ], ++ [ ++ Utils.DisplayWrapper.getMonitorManager(), ++ 'monitors-changed', ++ () => { ++ if (Main.layoutManager.primaryMonitor) { ++ this._saveMonitors(); ++ this._reset(); ++ } ++ } ++ ] ++ ); ++ ++ Panel.panelBoxes.forEach(c => this._signalsHandler.add( ++ [Main.panel[c], 'actor-added', (parent, child) => this._adjustPanelMenuButton(this._getPanelMenuButton(child), this.primaryPanel.monitor, this.primaryPanel.getPosition())] ++ )); ++ ++ this._setKeyBindings(true); ++ }, ++ ++ disable: function(reset) { ++ this.overview.disable(); ++ this.proximityManager.destroy(); ++ ++ this.allPanels.forEach(p => { ++ p.taskbar.iconAnimator.pause(); ++ ++ this._findPanelMenuButtons(p.panelBox).forEach(pmb => { ++ if (pmb.menu._boxPointer._dtpGetPreferredHeightId) { ++ pmb.menu._boxPointer._container.disconnect(pmb.menu._boxPointer._dtpGetPreferredHeightId); ++ } ++ ++ pmb.menu._boxPointer.sourceActor = pmb.menu._boxPointer._dtpSourceActor; ++ delete pmb.menu._boxPointer._dtpSourceActor; ++ pmb.menu._boxPointer._userArrowSide = St.Side.TOP; ++ }) ++ ++ this._removePanelBarriers(p); ++ ++ p.disable(); ++ ++ let clipContainer = p.panelBox.get_parent(); ++ ++ Main.layoutManager._untrackActor(p.panelBox); ++ Main.layoutManager.removeChrome(clipContainer); ++ ++ if (p.isStandalone) { ++ p.panelBox.destroy(); ++ } else { ++ p.panelBox.remove_child(p); ++ p.remove_child(p.panel.actor); ++ p.panelBox.add(p.panel.actor); ++ ++ p.panelBox.set_position(clipContainer.x, clipContainer.y); ++ ++ clipContainer.remove_child(p.panelBox); ++ Main.layoutManager.addChrome(p.panelBox, { affectsStruts: true, trackFullscreen: true }); ++ } ++ }); ++ ++ if (BoxPointer.BoxPointer.prototype.vfunc_get_preferred_height) { ++ Utils.hookVfunc(BoxPointer.BoxPointer.prototype, 'get_preferred_height', BoxPointer.BoxPointer.prototype.vfunc_get_preferred_height); ++ } ++ ++ delete Main.wm._getPositionForDirection; ++ ++ if (Main.layoutManager.primaryMonitor) { ++ Main.layoutManager.panelBox.set_position(Main.layoutManager.primaryMonitor.x, Main.layoutManager.primaryMonitor.y); ++ Main.layoutManager.panelBox.set_size(Main.layoutManager.primaryMonitor.width, -1); ++ } ++ ++ if (reset) return; ++ ++ this._setKeyBindings(false); ++ ++ this._signalsHandler.destroy(); ++ ++ Main.layoutManager._updateHotCorners = this._oldUpdateHotCorners; ++ Main.layoutManager._updateHotCorners(); ++ ++ Me.settings.disconnect(this._forceHotCornerId); ++ ++ if (this._enableHotCornersId) { ++ Main.layoutManager._interfaceSettings.disconnect(this._enableHotCornersId); ++ } ++ ++ Main.layoutManager._updatePanelBarrier = this._oldUpdatePanelBarrier; ++ Main.layoutManager._updatePanelBarrier(); ++ ++ Main.overview.viewSelector._animateIn = this._oldViewSelectorAnimateIn; ++ Main.overview.viewSelector._animateOut = this._oldViewSelectorAnimateOut; ++ ++ Main.overview._relayout = this._oldOverviewRelayout; ++ Main.overview._relayout(); ++ ++ Main.overview.viewSelector._workspacesDisplay._updateWorkspacesViews = this._oldUpdateWorkspacesViews; ++ ++ Utils.getPanelGhost().set_size(-1, -1); ++ ++ if (this._oldDoSpringAnimation) { ++ AppDisplay.BaseAppView.prototype._doSpringAnimation = this._oldDoSpringAnimation; ++ } ++ ++ if (this._oldAnimateIconPosition) { ++ IconGrid.animateIconPosition = this._oldAnimateIconPosition; ++ } ++ ++ LookingGlass.LookingGlass.prototype._resize = LookingGlass.LookingGlass.prototype._oldResize; ++ delete LookingGlass.LookingGlass.prototype._oldResize; ++ ++ LookingGlass.LookingGlass.prototype.open = LookingGlass.LookingGlass.prototype._oldOpen; ++ delete LookingGlass.LookingGlass.prototype._oldOpen ++ }, ++ ++ setFocusedMonitor: function(monitor, ignoreRelayout) { ++ this._needsIconAllocate = 1; ++ ++ if (!this.checkIfFocusedMonitor(monitor)) { ++ Main.overview.viewSelector._workspacesDisplay._primaryIndex = monitor.index; ++ ++ Main.overview._overview.clear_constraints(); ++ Main.overview._overview.add_constraint(new Layout.MonitorConstraint({ index: monitor.index })); ++ ++ if (ignoreRelayout) return; ++ ++ this._newOverviewRelayout.call(Main.overview); ++ } ++ }, ++ ++ _saveMonitors: function() { ++ //Mutter meta_monitor_manager_get_primary_monitor (global.display.get_primary_monitor()) doesn't return the same ++ //monitor as GDK gdk_screen_get_primary_monitor (imports.gi.Gdk.Screen.get_default().get_primary_monitor()). ++ //Since the Mutter function is what's used in gnome-shell and we can't access it from the settings dialog, store ++ //the monitors information in a setting so we can use the same monitor indexes as the ones in gnome-shell ++ let primaryIndex = Main.layoutManager.primaryIndex; ++ let monitors = [primaryIndex]; ++ ++ Main.layoutManager.monitors.filter(m => m.index != primaryIndex).forEach(m => monitors.push(m.index)); ++ Me.settings.set_value('available-monitors', new GLib.Variant('ai', monitors)); ++ }, ++ ++ checkIfFocusedMonitor: function(monitor) { ++ return Main.overview.viewSelector._workspacesDisplay._primaryIndex == monitor.index; ++ }, ++ ++ _createPanel: function(monitor, isStandalone) { ++ let panelBox; ++ let panel; ++ let clipContainer = new Clutter.Actor(); ++ ++ if (isStandalone) { ++ panelBox = new St.BoxLayout({ name: 'panelBox' }); ++ } else { ++ panelBox = Main.layoutManager.panelBox; ++ Main.layoutManager._untrackActor(panelBox); ++ panelBox.remove_child(Main.panel.actor); ++ Main.layoutManager.removeChrome(panelBox); ++ } ++ ++ Main.layoutManager.addChrome(clipContainer, { affectsInputRegion: false }); ++ clipContainer.add_child(panelBox); ++ Main.layoutManager.trackChrome(panelBox, { trackFullscreen: true, affectsStruts: true, affectsInputRegion: true }); ++ ++ panel = new Panel.dtpPanel(this, monitor, panelBox, isStandalone); ++ panelBox.add(panel); ++ panel.enable(); ++ ++ panelBox.visible = !monitor.inFullscreen; ++ panelBox.set_position(0, 0); ++ ++ return panel; ++ }, ++ ++ _reset: function() { ++ this.disable(true); ++ this.allPanels = []; ++ this.enable(true); ++ }, ++ ++ _updatePanelElementPositions: function() { ++ this.panelsElementPositions = PanelSettings.getSettingsJson(Me.settings, 'panel-element-positions'); ++ this.allPanels.forEach(p => p.updateElementPositions()); ++ }, ++ ++ _adjustPanelMenuButton: function(button, monitor, arrowSide) { ++ if (button) { ++ Utils.wrapActor(button); ++ button.menu._boxPointer._dtpSourceActor = button.menu._boxPointer.sourceActor; ++ button.menu._boxPointer.sourceActor = button.actor; ++ button.menu._boxPointer._userArrowSide = arrowSide; ++ button.menu._boxPointer._dtpInPanel = 1; ++ ++ if (!button.menu._boxPointer.vfunc_get_preferred_height) { ++ button.menu._boxPointer._dtpGetPreferredHeightId = button.menu._boxPointer._container.connect('get-preferred-height', (actor, forWidth, alloc) => { ++ this._getBoxPointerPreferredHeight(button.menu._boxPointer, alloc, monitor); ++ }); ++ } ++ } ++ }, ++ ++ _getBoxPointerPreferredHeight: function(boxPointer, alloc, monitor) { ++ if (boxPointer._dtpInPanel && boxPointer.sourceActor && Me.settings.get_boolean('intellihide')) { ++ monitor = monitor || Main.layoutManager.findMonitorForActor(boxPointer.sourceActor); ++ let panel = Utils.find(global.dashToPanel.panels, p => p.monitor == monitor); ++ let excess = alloc.natural_size + panel.dtpSize + 10 - monitor.height; // 10 is arbitrary ++ ++ if (excess > 0) { ++ alloc.natural_size -= excess; ++ } ++ } ++ ++ return [alloc.min_size, alloc.natural_size]; ++ }, ++ ++ _findPanelMenuButtons: function(container) { ++ let panelMenuButtons = []; ++ let panelMenuButton; ++ ++ let find = parent => parent.get_children().forEach(c => { ++ if ((panelMenuButton = this._getPanelMenuButton(c))) { ++ panelMenuButtons.push(panelMenuButton); ++ } ++ ++ find(c); ++ }); ++ ++ find(container); ++ ++ return panelMenuButtons; ++ }, ++ ++ _removePanelBarriers: function(panel) { ++ if (panel.isStandalone && panel._rightPanelBarrier) { ++ panel._rightPanelBarrier.destroy(); ++ } ++ ++ if (panel._leftPanelBarrier) { ++ panel._leftPanelBarrier.destroy(); ++ delete panel._leftPanelBarrier; ++ } ++ }, ++ ++ _getPanelMenuButton: function(obj) { ++ return obj._delegate && obj._delegate instanceof PanelMenu.Button ? obj._delegate : 0; ++ }, ++ ++ _setKeyBindings: function(enable) { ++ let keys = { ++ 'intellihide-key-toggle': () => this.allPanels.forEach(p => p.intellihide.toggle()) ++ }; ++ ++ Object.keys(keys).forEach(k => { ++ Utils.removeKeybinding(k); ++ ++ if (enable) { ++ Utils.addKeybinding(k, Me.settings, keys[k], Shell.ActionMode.NORMAL); ++ } ++ }); ++ }, ++ ++ _newOverviewRelayout: function() { ++ // To avoid updating the position and size of the workspaces ++ // we just hide the overview. The positions will be updated ++ // when it is next shown. ++ this.hide(); ++ ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.overview.viewSelector._workspacesDisplay._primaryIndex); ++ ++ this._coverPane.set_position(0, workArea.y); ++ this._coverPane.set_size(workArea.width, workArea.height); ++ ++ this._updateBackgrounds(); ++ }, ++ ++ _newUpdateWorkspacesViews: function() { ++ for (let i = 0; i < this._workspacesViews.length; i++) ++ this._workspacesViews[i].destroy(); ++ ++ this._workspacesViews = []; ++ ++ let monitors = Main.layoutManager.monitors; ++ ++ for (let i = 0; i < monitors.length; i++) { ++ let workspaces; ++ let view; ++ if (this._workspacesOnlyOnPrimary && i != Main.layoutManager.primaryIndex) { ++ view = new WorkspacesView.ExtraWorkspaceView(i); ++ view.getActiveWorkspace = view.getActiveWorkspace || function() { return this._workspace; }; ++ workspaces = [view._workspace]; ++ } else { ++ view = new WorkspacesView.WorkspacesView(i, this._scrollAdjustment || 0); ++ workspaces = view._workspaces; ++ } ++ ++ Utils.wrapActor(view); ++ view.actor.connect('scroll-event', this._onScrollEvent.bind(this)); ++ if (i == Main.layoutManager.primaryIndex && view.scrollAdjustment) { ++ this._scrollAdjustment = view.scrollAdjustment; ++ this._scrollAdjustment.connect('notify::value', ++ this._scrollValueChanged.bind(this)); ++ } ++ ++ workspaces.forEach(w => w.setFullGeometry = geom => w._fullGeometry = geom); ++ this._workspacesViews.push(view); ++ } ++ ++ this._workspacesViews.forEach(wv => Main.layoutManager.overviewGroup.add_actor(wv.actor)); ++ ++ if (this._syncWorkspacesFullGeometry) { ++ //gnome-shell 3.36.4 ++ if (this._fullGeometry) ++ this._syncWorkspacesFullGeometry(); ++ if (this._actualGeometry) ++ this._syncWorkspacesActualGeometry(); ++ } else if (this._updateWorkspacesFullGeometry) { ++ this._updateWorkspacesFullGeometry(); ++ this._updateWorkspacesActualGeometry(); ++ } ++ }, ++ ++ _newGetShowAppsButton: function() { ++ let focusedMonitorIndex = Utils.findIndex(this.allPanels, p => this.checkIfFocusedMonitor(p.monitor)); ++ ++ return this.allPanels[focusedMonitorIndex].taskbar.showAppsButton; ++ } ++}); ++ ++// This class drives long-running icon animations, to keep them running in sync ++// with each other. ++var IconAnimator = Utils.defineClass({ ++ Name: 'DashToPanel.IconAnimator', ++ ++ _init: function(actor) { ++ this._count = 0; ++ this._started = false; ++ this._animations = { ++ dance: [], ++ }; ++ this._timeline = new Clutter.Timeline({ ++ duration: 3000, ++ repeat_count: -1, ++ }); ++ ++ /* Just use the construction property when no need to support 3.36 */ ++ if (this._timeline.set_actor) ++ this._timeline.set_actor(actor); ++ ++ this._timeline.connect('new-frame', () => { ++ const progress = this._timeline.get_progress(); ++ const danceRotation = progress < 1/6 ? 15*Math.sin(progress*24*Math.PI) : 0; ++ const dancers = this._animations.dance; ++ for (let i = 0, iMax = dancers.length; i < iMax; i++) { ++ dancers[i].target.rotation_angle_z = danceRotation; ++ } ++ }); ++ }, ++ ++ destroy: function() { ++ this._timeline.stop(); ++ this._timeline = null; ++ for (let name in this._animations) { ++ const pairs = this._animations[name]; ++ for (let i = 0, iMax = pairs.length; i < iMax; i++) { ++ const pair = pairs[i]; ++ pair.target.disconnect(pair.targetDestroyId); ++ } ++ } ++ this._animations = null; ++ }, ++ ++ pause: function() { ++ if (this._started && this._count > 0) { ++ this._timeline.stop(); ++ } ++ this._started = false; ++ }, ++ ++ start: function() { ++ if (!this._started && this._count > 0) { ++ this._timeline.start(); ++ } ++ this._started = true; ++ }, ++ ++ addAnimation: function(target, name) { ++ const targetDestroyId = target.connect('destroy', () => this.removeAnimation(target, name)); ++ this._animations[name].push({ target: target, targetDestroyId: targetDestroyId }); ++ if (this._started && this._count === 0) { ++ this._timeline.start(); ++ } ++ this._count++; ++ }, ++ ++ removeAnimation: function(target, name) { ++ const pairs = this._animations[name]; ++ for (let i = 0, iMax = pairs.length; i < iMax; i++) { ++ const pair = pairs[i]; ++ if (pair.target === target) { ++ target.disconnect(pair.targetDestroyId); ++ pairs.splice(i, 1); ++ this._count--; ++ if (this._started && this._count === 0) { ++ this._timeline.stop(); ++ } ++ return; ++ } ++ } ++ } ++}); ++ ++function newViewSelectorAnimateIn(oldPage) { ++ if (oldPage) ++ oldPage.hide(); ++ ++ let vs = Main.overview.viewSelector; ++ ++ vs.emit('page-empty'); ++ ++ vs._activePage.show(); ++ ++ if (vs._activePage == vs._appsPage && oldPage == vs._workspacesPage) { ++ // Restore opacity, in case we animated via _fadePageOut ++ vs._activePage.opacity = 255; ++ let animate = Me.settings.get_boolean('animate-show-apps'); ++ if(animate) ++ vs.appDisplay.animate(IconGrid.AnimationDirection.IN); ++ } else { ++ vs._fadePageIn(); ++ } ++} ++ ++function newViewSelectorAnimateOut(page) { ++ let oldPage = page; ++ let vs = Main.overview.viewSelector; ++ ++ if (page == vs._appsPage && ++ vs._activePage == vs._workspacesPage && ++ !Main.overview.animationInProgress) { ++ let animate = Me.settings.get_boolean('animate-show-apps'); ++ if(animate) ++ vs.appDisplay.animate(IconGrid.AnimationDirection.OUT, Lang.bind(this, ++ function() { ++ vs._animateIn(oldPage) ++ })); ++ else ++ vs._animateIn(oldPage) ++ } else { ++ vs._fadePageOut(page); ++ } ++} ++ ++function newGetPositionForDirection(direction, fromWs, toWs) { ++ let [xDest, yDest] = WM.WindowManager.prototype._getPositionForDirection(direction, fromWs, toWs); ++ ++ if (direction == Meta.MotionDirection.UP || ++ direction == Meta.MotionDirection.UP_LEFT || ++ direction == Meta.MotionDirection.UP_RIGHT) { ++ yDest -= Main.panel.height; ++ } else if (direction != Meta.MotionDirection.LEFT && ++ direction != Meta.MotionDirection.RIGHT) { ++ yDest += Main.panel.height; ++ } ++ ++ return [xDest, yDest]; ++} ++ ++function newDoSpringAnimation(animationDirection) { ++ this._grid.opacity = 255; ++ this._grid.animateSpring(animationDirection, Main.overview.getShowAppsButton()); ++} ++ ++function newAnimateIconPosition(icon, box, flags, nChangedIcons) { ++ if (this._needsIconAllocate) { ++ Utils.allocate(icon, box, flags); ++ return; ++ } ++ ++ return this._oldAnimateIconPosition(icon, box, flags, nChangedIcons);; ++} ++ ++function newUpdateHotCorners() { ++ // destroy old hot corners ++ this.hotCorners.forEach(function(corner) { ++ if (corner) ++ corner.destroy(); ++ }); ++ this.hotCorners = []; ++ ++ //global.settings is ubuntu specific setting to disable the hot corner (Tweak tool > Top Bar > Activities Overview Hot Corner) ++ //this._interfaceSettings is for the setting to disable the hot corner introduced in gnome-shell 3.34 ++ if ((global.settings.list_keys().indexOf('enable-hot-corners') >= 0 && !global.settings.get_boolean('enable-hot-corners')) || ++ (this._interfaceSettings && !this._interfaceSettings.get_boolean('enable-hot-corners'))) { ++ this.emit('hot-corners-changed'); ++ return; ++ } ++ ++ // build new hot corners ++ for (let i = 0; i < this.monitors.length; i++) { ++ let panel = Utils.find(global.dashToPanel.panels, p => p.monitor.index == i); ++ let panelPosition = panel ? panel.getPosition() : St.Side.BOTTOM; ++ let panelTopLeft = panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT; ++ let monitor = this.monitors[i]; ++ let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x; ++ let cornerY = monitor.y; ++ ++ let haveTopLeftCorner = true; ++ ++ // If the panel is on the bottom, unless this is explicitly forced, don't add a topleft ++ // hot corner unless it is actually a top left panel. Otherwise, it stops the mouse ++ // as you are dragging across. In the future, maybe we will automatically move the ++ // hotcorner to the bottom when the panel is positioned at the bottom ++ if (i != this.primaryIndex || (!panelTopLeft && !Me.settings.get_boolean('stockgs-force-hotcorner'))) { ++ // Check if we have a top left (right for RTL) corner. ++ // I.e. if there is no monitor directly above or to the left(right) ++ let besideX = this._rtl ? monitor.x + 1 : cornerX - 1; ++ let besideY = cornerY; ++ let aboveX = cornerX; ++ let aboveY = cornerY - 1; ++ ++ for (let j = 0; j < this.monitors.length; j++) { ++ if (i == j) ++ continue; ++ let otherMonitor = this.monitors[j]; ++ if (besideX >= otherMonitor.x && ++ besideX < otherMonitor.x + otherMonitor.width && ++ besideY >= otherMonitor.y && ++ besideY < otherMonitor.y + otherMonitor.height) { ++ haveTopLeftCorner = false; ++ break; ++ } ++ if (aboveX >= otherMonitor.x && ++ aboveX < otherMonitor.x + otherMonitor.width && ++ aboveY >= otherMonitor.y && ++ aboveY < otherMonitor.y + otherMonitor.height) { ++ haveTopLeftCorner = false; ++ break; ++ } ++ } ++ } ++ ++ if (haveTopLeftCorner) { ++ let corner = new Layout.HotCorner(this, monitor, cornerX, cornerY); ++ ++ corner.setBarrierSize = size => corner.__proto__.setBarrierSize.call(corner, Math.min(size, 32)); ++ corner.setBarrierSize(panel ? panel.dtpSize : 32); ++ this.hotCorners.push(corner); ++ } else { ++ this.hotCorners.push(null); ++ } ++ } ++ ++ this.emit('hot-corners-changed'); ++} ++ ++function newUpdatePanelBarrier(panel) { ++ let barriers = { ++ _rightPanelBarrier: [(panel.isStandalone ? panel : this)], ++ _leftPanelBarrier: [panel] ++ }; ++ ++ Object.keys(barriers).forEach(k => { ++ let obj = barriers[k][0]; ++ ++ if (obj[k]) { ++ obj[k].destroy(); ++ obj[k] = null; ++ } ++ }); ++ ++ if (!this.primaryMonitor || !panel.panelBox.height) { ++ return; ++ } ++ ++ let barrierSize = Math.min(10, panel.panelBox.height); ++ let fixed1 = panel.monitor.y; ++ let fixed2 = panel.monitor.y + barrierSize; ++ ++ if (panel.checkIfVertical()) { ++ barriers._rightPanelBarrier.push(panel.monitor.y + panel.monitor.height, Meta.BarrierDirection.POSITIVE_Y); ++ barriers._leftPanelBarrier.push(panel.monitor.y, Meta.BarrierDirection.NEGATIVE_Y); ++ } else { ++ barriers._rightPanelBarrier.push(panel.monitor.x + panel.monitor.width, Meta.BarrierDirection.NEGATIVE_X); ++ barriers._leftPanelBarrier.push(panel.monitor.x, Meta.BarrierDirection.POSITIVE_X); ++ } ++ ++ switch (panel.getPosition()) { ++ //values are initialized as St.Side.TOP ++ case St.Side.BOTTOM: ++ fixed1 = panel.monitor.y + panel.monitor.height - barrierSize; ++ fixed2 = panel.monitor.y + panel.monitor.height; ++ break; ++ case St.Side.LEFT: ++ fixed1 = panel.monitor.x; ++ fixed2 = panel.monitor.x + barrierSize; ++ break; ++ case St.Side.RIGHT: ++ fixed1 = panel.monitor.x + panel.monitor.width; ++ fixed2 = panel.monitor.x + panel.monitor.width - barrierSize; ++ break; ++ } ++ ++ //remove left barrier if it overlaps one of the hotcorners ++ for (let k in this.hotCorners) { ++ let hc = this.hotCorners[k]; ++ ++ if (hc && hc._monitor == panel.monitor && ++ ((fixed1 == hc._x || fixed2 == hc._x) || fixed1 == hc._y || fixed2 == hc._y)) { ++ delete barriers._leftPanelBarrier; ++ break; ++ } ++ } ++ ++ Object.keys(barriers).forEach(k => { ++ let barrierOptions = { ++ display: global.display, ++ directions: barriers[k][2] ++ }; ++ ++ barrierOptions[panel.varCoord.c1] = barrierOptions[panel.varCoord.c2] = barriers[k][1]; ++ barrierOptions[panel.fixedCoord.c1] = fixed1; ++ barrierOptions[panel.fixedCoord.c2] = fixed2; ++ ++ barriers[k][0][k] = new Meta.Barrier(barrierOptions); ++ }); ++} ++ ++function _newLookingGlassResize() { ++ let primaryMonitorPanel = Utils.find(global.dashToPanel.panels, p => p.monitor == Main.layoutManager.primaryMonitor); ++ let topOffset = primaryMonitorPanel.getPosition() == St.Side.TOP ? primaryMonitorPanel.dtpSize + 8 : 32; ++ ++ this._oldResize(); ++ Utils.wrapActor(this); ++ Utils.wrapActor(this._objInspector); ++ ++ this._hiddenY = Main.layoutManager.primaryMonitor.y + topOffset - this.actor.height; ++ this._targetY = this._hiddenY + this.actor.height; ++ this.actor.y = this._hiddenY; ++ ++ this._objInspector.actor.set_position(this.actor.x + Math.floor(this.actor.width * 0.1), this._targetY + Math.floor(this.actor.height * 0.1)); ++} ++ ++function _newLookingGlassOpen() { ++ if (this._open) ++ return; ++ ++ this._resize(); ++ this._oldOpen(); ++} +diff --git a/extensions/dash-to-panel/panelPositions.js b/extensions/dash-to-panel/panelPositions.js +new file mode 100644 +index 00000000..52458bb6 +--- /dev/null ++++ b/extensions/dash-to-panel/panelPositions.js +@@ -0,0 +1,61 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++var SHOW_APPS_BTN = 'showAppsButton'; ++var ACTIVITIES_BTN = 'activitiesButton'; ++var TASKBAR = 'taskbar'; ++var DATE_MENU = 'dateMenu'; ++var SYSTEM_MENU = 'systemMenu'; ++var LEFT_BOX = 'leftBox'; ++var CENTER_BOX = 'centerBox'; ++var RIGHT_BOX = 'rightBox'; ++var DESKTOP_BTN = 'desktopButton'; ++ ++var STACKED_TL = 'stackedTL'; ++var STACKED_BR = 'stackedBR'; ++var CENTERED = 'centered'; ++var CENTERED_MONITOR = 'centerMonitor'; ++ ++var TOP = 'TOP'; ++var BOTTOM = 'BOTTOM'; ++var LEFT = 'LEFT'; ++var RIGHT = 'RIGHT'; ++ ++var START = 'START'; ++var MIDDLE = 'MIDDLE'; ++var END = 'END'; ++ ++var defaults = [ ++ { element: SHOW_APPS_BTN, visible: true, position: STACKED_TL }, ++ { element: ACTIVITIES_BTN, visible: false, position: STACKED_TL }, ++ { element: LEFT_BOX, visible: true, position: STACKED_TL }, ++ { element: TASKBAR, visible: true, position: STACKED_TL }, ++ { element: CENTER_BOX, visible: true, position: STACKED_BR }, ++ { element: RIGHT_BOX, visible: true, position: STACKED_BR }, ++ { element: DATE_MENU, visible: true, position: STACKED_BR }, ++ { element: SYSTEM_MENU, visible: true, position: STACKED_BR }, ++ { element: DESKTOP_BTN, visible: true, position: STACKED_BR }, ++]; ++ ++var optionDialogFunctions = {}; ++ ++optionDialogFunctions[SHOW_APPS_BTN] = '_showShowAppsButtonOptions'; ++optionDialogFunctions[DESKTOP_BTN] = '_showDesktopButtonOptions'; ++ ++function checkIfCentered(position) { ++ return position == CENTERED || position == CENTERED_MONITOR; ++} +\ No newline at end of file +diff --git a/extensions/dash-to-panel/panelSettings.js b/extensions/dash-to-panel/panelSettings.js +new file mode 100644 +index 00000000..4feb3fd7 +--- /dev/null ++++ b/extensions/dash-to-panel/panelSettings.js +@@ -0,0 +1,112 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Pos = Me.imports.panelPositions; ++ ++/** Return object representing a settings value that is stored as JSON. */ ++function getSettingsJson(settings, setting) { ++ try { ++ return JSON.parse(settings.get_string(setting)); ++ } catch(e) { ++ log('Error parsing positions: ' + e.message); ++ } ++} ++/** Write value object as JSON to setting in settings. */ ++function setSettingsJson(settings, setting, value) { ++ try { ++ const json = JSON.stringify(value); ++ settings.set_string(setting, json); ++ } catch(e) { ++ log('Error serializing setting: ' + e.message); ++ } ++} ++ ++/** Returns size of panel on a specific monitor, in pixels. */ ++function getPanelSize(settings, monitorIndex) { ++ const sizes = getSettingsJson(settings, 'panel-sizes'); ++ // Pull in deprecated setting if panel-sizes does not have setting for monitor. ++ const fallbackSize = settings.get_int('panel-size'); ++ const theDefault = 48; ++ return sizes[monitorIndex] || fallbackSize || theDefault; ++} ++ ++function setPanelSize(settings, monitorIndex, value) { ++ if (!(Number.isInteger(value) && value <= 128 && value >= 16)) { ++ log('Not setting invalid panel size: ' + value); ++ return; ++ } ++ let sizes = getSettingsJson(settings, 'panel-sizes'); ++ sizes[monitorIndex] = value; ++ setSettingsJson(settings, 'panel-sizes', sizes); ++} ++ ++/** ++ * Returns length of panel on a specific monitor, as a whole number percent, ++ * from settings. e.g. 100 ++ */ ++function getPanelLength(settings, monitorIndex) { ++ const lengths = getSettingsJson(settings, 'panel-lengths'); ++ const theDefault = 100; ++ return lengths[monitorIndex] || theDefault; ++} ++ ++function setPanelLength(settings, monitorIndex, value) { ++ if (!(Number.isInteger(value) && value <= 100 && value >= 0)) { ++ log('Not setting invalid panel length: ' + value); ++ return; ++ } ++ let lengths = getSettingsJson(settings, 'panel-lengths'); ++ lengths[monitorIndex] = value; ++ setSettingsJson(settings, 'panel-lengths', lengths); ++} ++ ++/** Returns position of panel on a specific monitor. */ ++function getPanelPosition(settings, monitorIndex) { ++ const positions = getSettingsJson(settings, 'panel-positions'); ++ const fallbackPosition = settings.get_string('panel-position'); ++ const theDefault = Pos.BOTTOM; ++ return positions[monitorIndex] || fallbackPosition || theDefault; ++} ++ ++function setPanelPosition(settings, monitorIndex, value) { ++ if (!(value === Pos.TOP || value === Pos.BOTTOM || value === Pos.LEFT ++ || value === Pos.RIGHT)) { ++ log('Not setting invalid panel position: ' + value); ++ return; ++ } ++ const positions = getSettingsJson(settings, 'panel-positions'); ++ positions[monitorIndex] = value; ++ setSettingsJson(settings, 'panel-positions', positions); ++} ++ ++/** Returns anchor location of panel on a specific monitor. */ ++function getPanelAnchor(settings, monitorIndex) { ++ const anchors = getSettingsJson(settings, 'panel-anchors'); ++ const theDefault = Pos.MIDDLE; ++ return anchors[monitorIndex] || theDefault; ++} ++ ++function setPanelAnchor(settings, monitorIndex, value) { ++ if (!(value === Pos.START || value === Pos.MIDDLE || value === Pos.END)) { ++ log('Not setting invalid panel anchor: ' + value); ++ return; ++ } ++ const anchors = getSettingsJson(settings, 'panel-anchors'); ++ anchors[monitorIndex] = value; ++ setSettingsJson(settings, 'panel-anchors', anchors); ++} +diff --git a/extensions/dash-to-panel/panelStyle.js b/extensions/dash-to-panel/panelStyle.js +new file mode 100644 +index 00000000..2697ace2 +--- /dev/null ++++ b/extensions/dash-to-panel/panelStyle.js +@@ -0,0 +1,326 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * Credits: ++ * Ideas for recursing child actors and assigning inline styles ++ * are based on code from the StatusAreaHorizontalSpacing extension ++ * https://bitbucket.org/mathematicalcoffee/status-area-horizontal-spacing-gnome-shell-extension ++ * mathematical.coffee@gmail.com ++ */ ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const ExtensionUtils = imports.misc.extensionUtils; ++const Lang = imports.lang; ++const Main = imports.ui.main; ++const Mainloop = imports.mainloop; ++const St = imports.gi.St; ++const Shell = imports.gi.Shell; ++ ++const Panel = Me.imports.panel; ++const Taskbar = Me.imports.taskbar; ++const Utils = Me.imports.utils; ++ ++var dtpPanelStyle = Utils.defineClass({ ++ Name: 'DashToPanel.PanelStyle', ++ ++ _init: function() { ++ ++ }, ++ ++ enable : function(panel) { ++ this.panel = panel; ++ ++ this._applyStyles(); ++ ++ this._bindSettingsChanges(); ++ }, ++ ++ disable: function () { ++ for (let i = 0; i < this._dtpSettingsSignalIds.length; ++i) { ++ Me.settings.disconnect(this._dtpSettingsSignalIds[i]); ++ } ++ ++ this._removeStyles(); ++ }, ++ ++ _bindSettingsChanges: function() { ++ let configKeys = [ ++ "tray-size", ++ "leftbox-size", ++ "tray-padding", ++ "leftbox-padding", ++ "status-icon-padding", ++ ]; ++ ++ this._dtpSettingsSignalIds = []; ++ ++ for(let i in configKeys) { ++ this._dtpSettingsSignalIds.push(Me.settings.connect('changed::' + configKeys[i], Lang.bind(this, function () { ++ this._removeStyles(); ++ this._applyStyles(); ++ }))); ++ } ++ }, ++ ++ _applyStyles: function() { ++ this._rightBoxOperations = []; ++ ++ let trayPadding = Me.settings.get_int('tray-padding'); ++ let isVertical = this.panel.checkIfVertical(); ++ let paddingStyle = 'padding: ' + (isVertical ? '%dpx 0' : '0 %dpx'); ++ ++ if(trayPadding >= 0) { ++ let operation = {}; ++ let trayPaddingStyleLine; ++ ++ if (isVertical) { ++ trayPaddingStyleLine = paddingStyle.format(trayPadding); ++ operation.compareFn = function (actor) { ++ let parent = actor.get_parent(); ++ return (parent && parent.has_style_class_name && parent.has_style_class_name('panel-button')); ++ }; ++ } else { ++ trayPaddingStyleLine = '-natural-hpadding: %dpx'.format(trayPadding); ++ if (trayPadding < 6) { ++ trayPaddingStyleLine += '; -minimum-hpadding: %dpx'.format(trayPadding); ++ } ++ ++ operation.compareFn = function (actor) { ++ return (actor.has_style_class_name && actor.has_style_class_name('panel-button')); ++ }; ++ } ++ ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, trayPaddingStyleLine, operationIdx); ++ this._refreshPanelButton(actor); ++ }); ++ this._rightBoxOperations.push(operation); ++ } ++ ++ let statusIconPadding = Me.settings.get_int('status-icon-padding'); ++ if(statusIconPadding >= 0) { ++ let statusIconPaddingStyleLine = paddingStyle.format(statusIconPadding) ++ let operation = {}; ++ operation.compareFn = function (actor) { ++ return (actor.has_style_class_name && actor.has_style_class_name('system-status-icon')); ++ }; ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, statusIconPaddingStyleLine, operationIdx); ++ }); ++ this._rightBoxOperations.push(operation); ++ } ++ ++ let trayContentSize = Me.settings.get_int('tray-size'); ++ if(trayContentSize > 0) { ++ let trayIconSizeStyleLine = 'icon-size: %dpx'.format(trayContentSize) ++ let operation = {}; ++ operation.compareFn = function (actor) { ++ return (actor.constructor && actor.constructor.name == 'St_Icon'); ++ }; ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, trayIconSizeStyleLine, operationIdx); ++ }); ++ this._rightBoxOperations.push(operation); ++ ++ let trayContentSizeStyleLine = 'font-size: %dpx'.format(trayContentSize) ++ operation = {}; ++ operation.compareFn = function (actor) { ++ return (actor.constructor && actor.constructor.name == 'St_Label'); ++ }; ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, trayContentSizeStyleLine, operationIdx); ++ }); ++ this._rightBoxOperations.push(operation); ++ ++ this._overrideStyle(this.panel._rightBox, trayContentSizeStyleLine, 0); ++ this._overrideStyle(this.panel._centerBox, trayContentSizeStyleLine, 0); ++ } ++ ++ // center box has been moved next to the right box and will be treated the same ++ this._centerBoxOperations = this._rightBoxOperations; ++ ++ this._leftBoxOperations = []; ++ ++ let leftboxPadding = Me.settings.get_int('leftbox-padding'); ++ if(leftboxPadding >= 0) { ++ let leftboxPaddingStyleLine = paddingStyle.format(leftboxPadding); ++ let operation = {}; ++ operation.compareFn = function (actor) { ++ let parent = actor.get_parent(); ++ return (parent && parent.has_style_class_name && parent.has_style_class_name('panel-button')); ++ }; ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, leftboxPaddingStyleLine, operationIdx); ++ }); ++ this._leftBoxOperations.push(operation); ++ } ++ ++ let leftboxContentSize = Me.settings.get_int('leftbox-size'); ++ if(leftboxContentSize > 0) { ++ let leftboxIconSizeStyleLine = 'icon-size: %dpx'.format(leftboxContentSize) ++ let operation = {}; ++ operation.compareFn = function (actor) { ++ return (actor.constructor && actor.constructor.name == 'St_Icon'); ++ }; ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, leftboxIconSizeStyleLine, operationIdx); ++ }); ++ this._leftBoxOperations.push(operation); ++ ++ let leftboxContentSizeStyleLine = 'font-size: %dpx'.format(leftboxContentSize) ++ operation = {}; ++ operation.compareFn = function (actor) { ++ return (actor.constructor && actor.constructor.name == 'St_Label'); ++ }; ++ operation.applyFn = Lang.bind(this, function (actor, operationIdx) { ++ this._overrideStyle(actor, leftboxContentSizeStyleLine, operationIdx); ++ }); ++ this._leftBoxOperations.push(operation); ++ ++ this._overrideStyle(this.panel._leftBox, leftboxContentSizeStyleLine, 0); ++ } ++ ++ this._applyStylesRecursively(); ++ ++ /* connect signal */ ++ this._rightBoxActorAddedID = this.panel._rightBox.connect('actor-added', ++ Lang.bind(this, function (container, actor) { ++ if(this._rightBoxOperations.length && !this._ignoreAddedChild) ++ this._recursiveApply(actor, this._rightBoxOperations); ++ ++ this._ignoreAddedChild = 0; ++ }) ++ ); ++ this._centerBoxActorAddedID = this.panel._centerBox.connect('actor-added', ++ Lang.bind(this, function (container, actor) { ++ if(this._centerBoxOperations.length && !this._ignoreAddedChild) ++ this._recursiveApply(actor, this._centerBoxOperations); ++ ++ this._ignoreAddedChild = 0; ++ }) ++ ); ++ this._leftBoxActorAddedID = this.panel._leftBox.connect('actor-added', ++ Lang.bind(this, function (container, actor) { ++ if(this._leftBoxOperations.length) ++ this._recursiveApply(actor, this._leftBoxOperations); ++ }) ++ ); ++ }, ++ ++ _removeStyles: function() { ++ /* disconnect signal */ ++ if (this._rightBoxActorAddedID) ++ this.panel._rightBox.disconnect(this._rightBoxActorAddedID); ++ if (this._centerBoxActorAddedID) ++ this.panel._centerBox.disconnect(this._centerBoxActorAddedID); ++ if (this._leftBoxActorAddedID) ++ this.panel._leftBox.disconnect(this._leftBoxActorAddedID); ++ ++ this._restoreOriginalStyle(this.panel._rightBox); ++ this._restoreOriginalStyle(this.panel._centerBox); ++ this._restoreOriginalStyle(this.panel._leftBox); ++ ++ this._applyStylesRecursively(true); ++ }, ++ ++ _applyStylesRecursively: function(restore) { ++ /*recurse actors */ ++ if(this._rightBoxOperations.length) { ++ // add the system menu as we move it from the rightbox to the panel to position it independently ++ let children = this.panel._rightBox.get_children().concat([this.panel.statusArea.aggregateMenu.container]); ++ for(let i in children) ++ this._recursiveApply(children[i], this._rightBoxOperations, restore); ++ } ++ ++ if(this._centerBoxOperations.length) { ++ // add the date menu as we move it from the centerbox to the panel to position it independently ++ let children = this.panel._centerBox.get_children().concat([this.panel.statusArea.dateMenu.container]); ++ for(let i in children) ++ this._recursiveApply(children[i], this._centerBoxOperations, restore); ++ } ++ ++ if(this._leftBoxOperations.length) { ++ let children = this.panel._leftBox.get_children(); ++ for(let i in children) ++ this._recursiveApply(children[i], this._leftBoxOperations, restore); ++ } ++ }, ++ ++ _recursiveApply: function(actor, operations, restore) { ++ for(let i in operations) { ++ let o = operations[i]; ++ if(o.compareFn(actor)) ++ if(restore) ++ o.restoreFn ? o.restoreFn(actor) : this._restoreOriginalStyle(actor); ++ else ++ o.applyFn(actor, i); ++ } ++ ++ if(actor.get_children) { ++ let children = actor.get_children(); ++ for(let i in children) { ++ this._recursiveApply(children[i], operations, restore); ++ } ++ } ++ }, ++ ++ _overrideStyle: function(actor, styleLine, operationIdx) { ++ if (actor._dtp_original_inline_style === undefined) { ++ actor._dtp_original_inline_style = actor.get_style(); ++ } ++ ++ if(actor._dtp_style_overrides === undefined) { ++ actor._dtp_style_overrides = {}; ++ } ++ ++ actor._dtp_style_overrides[operationIdx] = styleLine; ++ let newStyleLine = ''; ++ for(let i in actor._dtp_style_overrides) ++ newStyleLine += actor._dtp_style_overrides[i] + '; '; ++ actor.set_style(newStyleLine + (actor._dtp_original_inline_style || '')); ++ }, ++ ++ _restoreOriginalStyle: function(actor) { ++ if (actor._dtp_original_inline_style !== undefined) { ++ actor.set_style(actor._dtp_original_inline_style); ++ delete actor._dtp_original_inline_style; ++ delete actor._dtp_style_overrides; ++ } ++ ++ if (actor.has_style_class_name('panel-button')) { ++ this._refreshPanelButton(actor); ++ } ++ }, ++ ++ _refreshPanelButton: function(actor) { ++ if (actor.visible && imports.misc.config.PACKAGE_VERSION >= '3.34.0') { ++ //force gnome 3.34+ to refresh (having problem with the -natural-hpadding) ++ let parent = actor.get_parent(); ++ let children = parent.get_children(); ++ let actorIndex = 0; ++ ++ if (children.length > 1) { ++ actorIndex = children.indexOf(actor); ++ } ++ ++ this._ignoreAddedChild = [this.panel._centerBox, this.panel._rightBox].indexOf(parent) >= 0; ++ ++ parent.remove_child(actor); ++ parent.insert_child_at_index(actor, actorIndex); ++ } ++ } ++ ++}); +diff --git a/extensions/dash-to-panel/prefs.js b/extensions/dash-to-panel/prefs.js +new file mode 100644 +index 00000000..d402d6bb +--- /dev/null ++++ b/extensions/dash-to-panel/prefs.js +@@ -0,0 +1,2433 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg. ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++const GdkPixbuf = imports.gi.GdkPixbuf; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const GObject = imports.gi.GObject; ++const Gtk = imports.gi.Gtk; ++const Gdk = imports.gi.Gdk; ++const Lang = imports.lang; ++const Mainloop = imports.mainloop; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Convenience = Me.imports.convenience; ++const Gettext = imports.gettext.domain(Me.metadata['gettext-domain']); ++const _ = Gettext.gettext; ++const N_ = function(e) { return e }; ++const PanelSettings = Me.imports.panelSettings; ++const Pos = Me.imports.panelPositions; ++ ++const SCALE_UPDATE_TIMEOUT = 500; ++const DEFAULT_PANEL_SIZES = [ 128, 96, 64, 48, 32, 24, 16 ]; ++const DEFAULT_FONT_SIZES = [ 96, 64, 48, 32, 24, 16, 0 ]; ++const DEFAULT_MARGIN_SIZES = [ 32, 24, 16, 12, 8, 4, 0 ]; ++const DEFAULT_PADDING_SIZES = [ 32, 24, 16, 12, 8, 4, 0, -1 ]; ++// Minimum length could be 0, but a higher value may help prevent confusion about where the panel went. ++const LENGTH_MARKS = [ 100, 90, 80, 70, 60, 50, 40, 30, 20, 10 ]; ++const MAX_WINDOW_INDICATOR = 4; ++ ++const SCHEMA_PATH = '/org/gnome/shell/extensions/dash-to-panel/'; ++const GSET = 'gnome-shell-extension-tool'; ++ ++/** ++ * This function was copied from the activities-config extension ++ * https://github.com/nls1729/acme-code/tree/master/activities-config ++ * by Norman L. Smith. ++ */ ++function cssHexString(css) { ++ let rrggbb = '#'; ++ let start; ++ for (let loop = 0; loop < 3; loop++) { ++ let end = 0; ++ let xx = ''; ++ for (let loop = 0; loop < 2; loop++) { ++ while (true) { ++ let x = css.slice(end, end + 1); ++ if ((x == '(') || (x == ',') || (x == ')')) ++ break; ++ end++; ++ } ++ if (loop == 0) { ++ end++; ++ start = end; ++ } ++ } ++ xx = parseInt(css.slice(start, end)).toString(16); ++ if (xx.length == 1) ++ xx = '0' + xx; ++ rrggbb += xx; ++ css = css.slice(end); ++ } ++ return rrggbb; ++} ++ ++function setShortcut(settings, shortcutName) { ++ let shortcut_text = settings.get_string(shortcutName + '-text'); ++ let [key, mods] = Gtk.accelerator_parse(shortcut_text); ++ ++ if (Gtk.accelerator_valid(key, mods)) { ++ let shortcut = Gtk.accelerator_name(key, mods); ++ settings.set_strv(shortcutName, [shortcut]); ++ } ++ else { ++ settings.set_strv(shortcutName, []); ++ } ++} ++ ++function checkHotkeyPrefix(settings) { ++ settings.delay(); ++ ++ let hotkeyPrefix = settings.get_string('hotkey-prefix-text'); ++ if (hotkeyPrefix == 'Super') ++ hotkeyPrefix = ''; ++ else if (hotkeyPrefix == 'SuperAlt') ++ hotkeyPrefix = ''; ++ let [, mods] = Gtk.accelerator_parse(hotkeyPrefix); ++ let [, shift_mods] = Gtk.accelerator_parse('' + hotkeyPrefix); ++ let [, ctrl_mods] = Gtk.accelerator_parse('' + hotkeyPrefix); ++ ++ let numHotkeys = 10; ++ for (let i = 1; i <= numHotkeys; i++) { ++ let number = i; ++ if (number == 10) ++ number = 0; ++ let key = Gdk.keyval_from_name(number.toString()); ++ let key_kp = Gdk.keyval_from_name('KP_' + number.toString()); ++ if (Gtk.accelerator_valid(key, mods)) { ++ let shortcut = Gtk.accelerator_name(key, mods); ++ let shortcut_kp = Gtk.accelerator_name(key_kp, mods); ++ ++ // Setup shortcut strings ++ settings.set_strv('app-hotkey-' + i, [shortcut]); ++ settings.set_strv('app-hotkey-kp-' + i, [shortcut_kp]); ++ ++ // With ++ shortcut = Gtk.accelerator_name(key, shift_mods); ++ shortcut_kp = Gtk.accelerator_name(key_kp, shift_mods); ++ settings.set_strv('app-shift-hotkey-' + i, [shortcut]); ++ settings.set_strv('app-shift-hotkey-kp-' + i, [shortcut_kp]); ++ ++ // With ++ shortcut = Gtk.accelerator_name(key, ctrl_mods); ++ shortcut_kp = Gtk.accelerator_name(key_kp, ctrl_mods); ++ settings.set_strv('app-ctrl-hotkey-' + i, [shortcut]); ++ settings.set_strv('app-ctrl-hotkey-kp-' + i, [shortcut_kp]); ++ } ++ else { ++ // Reset default settings for the relevant keys if the ++ // accelerators are invalid ++ let keys = ['app-hotkey-' + i, 'app-shift-hotkey-' + i, 'app-ctrl-hotkey-' + i, // Regular numbers ++ 'app-hotkey-kp-' + i, 'app-shift-hotkey-kp-' + i, 'app-ctrl-hotkey-kp-' + i]; // Key-pad numbers ++ keys.forEach(function(val) { ++ settings.set_value(val, settings.get_default_value(val)); ++ }, this); ++ } ++ } ++ ++ settings.apply(); ++} ++ ++function mergeObjects(main, bck) { ++ for (var prop in bck) { ++ if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) { ++ main[prop] = bck[prop]; ++ } ++ } ++ ++ return main; ++}; ++ ++const Settings = new Lang.Class({ ++ Name: 'DashToPanel.Settings', ++ ++ _init: function() { ++ this._settings = Convenience.getSettings('org.gnome.shell.extensions.dash-to-panel'); ++ ++ this._rtl = (Gtk.Widget.get_default_direction() == Gtk.TextDirection.RTL); ++ ++ this._builder = new Gtk.Builder(); ++ this._builder.set_translation_domain(Me.metadata['gettext-domain']); ++ this._builder.add_from_file(Me.path + '/Settings.ui'); ++ ++ this.notebook = this._builder.get_object('settings_notebook'); ++ this.viewport = new Gtk.Viewport(); ++ this.viewport.add(this.notebook); ++ this.widget = new Gtk.ScrolledWindow(); ++ this.widget.add(this.viewport); ++ ++ ++ // Timeout to delay the update of the settings ++ this._panel_size_timeout = 0; ++ this._dot_height_timeout = 0; ++ this._tray_size_timeout = 0; ++ this._leftbox_size_timeout = 0; ++ this._appicon_margin_timeout = 0; ++ this._appicon_padding_timeout = 0; ++ this._opacity_timeout = 0; ++ this._tray_padding_timeout = 0; ++ this._statusicon_padding_timeout = 0; ++ this._leftbox_padding_timeout = 0; ++ ++ this._bindSettings(); ++ ++ this._builder.connect_signals_full(Lang.bind(this, this._connector)); ++ }, ++ ++ /** ++ * Connect signals ++ */ ++ _connector: function(builder, object, signal, handler) { ++ object.connect(signal, Lang.bind(this, this._SignalHandler[handler])); ++ }, ++ ++ _updateVerticalRelatedOptions: function() { ++ let position = this._getPanelPosition(this._currentMonitorIndex); ++ let isVertical = position == Pos.LEFT || position == Pos.RIGHT; ++ let showDesktopWidthLabel = this._builder.get_object('show_showdesktop_width_label'); ++ ++ showDesktopWidthLabel.set_text(isVertical ? _('Show Desktop button height (px)') : _('Show Desktop button width (px)')); ++ ++ this._displayPanelPositionsForMonitor(this._currentMonitorIndex); ++ }, ++ ++ _maybeDisableTopPosition: function() { ++ let keepTopPanel = this._settings.get_boolean('stockgs-keep-top-panel'); ++ let monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ let topAvailable = !keepTopPanel || (!monitorSync && this._currentMonitorIndex != this.monitors[0]); ++ let topRadio = this._builder.get_object('position_top_button'); ++ ++ topRadio.set_sensitive(topAvailable); ++ topRadio.set_tooltip_text(!topAvailable ? _('Unavailable when gnome-shell top panel is present') : ''); ++ }, ++ ++ _getPanelPosition: function(monitorIndex) { ++ return PanelSettings.getPanelPosition(this._settings, monitorIndex); ++ }, ++ ++ _setPanelPosition: function(position) { ++ const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; ++ monitorsToSetFor.forEach(monitorIndex => { ++ PanelSettings.setPanelPosition(this._settings, monitorIndex, position); ++ }); ++ this._setAnchorLabels(this._currentMonitorIndex); ++ }, ++ ++ _setPositionRadios: function(position) { ++ this._ignorePositionRadios = true; ++ ++ switch (position) { ++ case Pos.BOTTOM: ++ this._builder.get_object('position_bottom_button').set_active(true); ++ break; ++ case Pos.TOP: ++ this._builder.get_object('position_top_button').set_active(true); ++ break; ++ case Pos.LEFT: ++ this._builder.get_object('position_left_button').set_active(true); ++ break; ++ case Pos.RIGHT: ++ this._builder.get_object('position_right_button').set_active(true); ++ break; ++ } ++ ++ this._ignorePositionRadios = false; ++ }, ++ ++ /** ++ * Set panel anchor combo labels according to whether the monitor's panel is vertical ++ * or horizontal, or if all monitors' panels are being configured and they are a mix ++ * of vertical and horizontal. ++ */ ++ _setAnchorLabels: function(currentMonitorIndex) { ++ const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ const monitorsToSetFor = monitorSync ? this.monitors : [currentMonitorIndex]; ++ const allVertical = monitorsToSetFor.every(i => { ++ const position = PanelSettings.getPanelPosition(this._settings, i); ++ return position === Pos.LEFT || position === Pos.RIGHT ++ }); ++ const allHorizontal = monitorsToSetFor.every(i => { ++ const position = PanelSettings.getPanelPosition(this._settings, i); ++ return position === Pos.TOP || position === Pos.BOTTOM; ++ }); ++ ++ const anchor_combo = this._builder.get_object('panel_anchor_combo'); ++ anchor_combo.remove_all(); ++ ++ if (allHorizontal) { ++ anchor_combo.append(Pos.START, _('Left')); ++ anchor_combo.append(Pos.MIDDLE, _('Center')); ++ anchor_combo.append(Pos.END, _('Right')); ++ } else if (allVertical) { ++ anchor_combo.append(Pos.START, _('Top')); ++ anchor_combo.append(Pos.MIDDLE, _('Middle')); ++ anchor_combo.append(Pos.END, _('Bottom')); ++ } else { ++ // Setting for a mix of horizontal and vertical panels on different monitors. ++ anchor_combo.append(Pos.START, _('Start')); ++ anchor_combo.append(Pos.MIDDLE, _('Middle')); ++ anchor_combo.append(Pos.END, _('End')); ++ } ++ ++ // Set combo box after re-populating its options. But only if it's for a single-panel ++ // configuration, or a multi-panel configuration where they all have the same anchor ++ // setting. So don't set the combo box if there is a multi-panel configuration with ++ // different anchor settings. ++ const someAnchor = PanelSettings.getPanelAnchor(this._settings, currentMonitorIndex); ++ if (monitorsToSetFor.every(i => ++ PanelSettings.getPanelAnchor(this._settings, i) === someAnchor)) { ++ const panel_anchor = PanelSettings.getPanelAnchor(this._settings, currentMonitorIndex); ++ this._builder.get_object('panel_anchor_combo').set_active_id(panel_anchor); ++ } ++ }, ++ ++ /** ++ * When a monitor is selected, update the widgets for panel position, size, anchoring, ++ * and contents so they accurately show the settings for the panel on that monitor. ++ */ ++ _updateWidgetSettingsForMonitor: function(monitorIndex) { ++ // Update display of panel screen position setting ++ this._maybeDisableTopPosition(); ++ const panelPosition = this._getPanelPosition(monitorIndex); ++ this._setPositionRadios(panelPosition); ++ ++ // Update display of thickness, length, and anchor settings ++ const panel_size_scale = this._builder.get_object('panel_size_scale'); ++ const size = PanelSettings.getPanelSize(this._settings, monitorIndex); ++ panel_size_scale.set_value(size); ++ ++ const panel_length_scale = this._builder.get_object('panel_length_scale'); ++ const length = PanelSettings.getPanelLength(this._settings, monitorIndex); ++ panel_length_scale.set_value(length); ++ this._setAnchorWidgetSensitivity(length); ++ ++ this._setAnchorLabels(monitorIndex); ++ ++ // Update display of panel content settings ++ this._displayPanelPositionsForMonitor(monitorIndex); ++ }, ++ ++ /** ++ * Anchor is only relevant if panel length is less than 100%. Enable or disable ++ * anchor widget sensitivity accordingly. ++ */ ++ _setAnchorWidgetSensitivity: function(panelLength) { ++ const isPartialLength = panelLength < 100; ++ this._builder.get_object('panel_anchor_label').set_sensitive(isPartialLength); ++ this._builder.get_object('panel_anchor_combo').set_sensitive(isPartialLength); ++ }, ++ ++ _displayPanelPositionsForMonitor: function(monitorIndex) { ++ let taskbarListBox = this._builder.get_object('taskbar_display_listbox'); ++ ++ taskbarListBox.get_children().forEach(c => c.destroy()); ++ ++ let labels = {}; ++ let panelPosition = this._getPanelPosition(monitorIndex); ++ let isVertical = panelPosition == Pos.LEFT || panelPosition == Pos.RIGHT; ++ let panelElementPositionsSettings = PanelSettings.getSettingsJson(this._settings, 'panel-element-positions'); ++ let panelElementPositions = panelElementPositionsSettings[monitorIndex] || Pos.defaults; ++ let updateElementsSettings = () => { ++ let newPanelElementPositions = []; ++ let monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ let monitors = monitorSync ? this.monitors : [monitorIndex]; ++ ++ taskbarListBox.get_children().forEach(c => { ++ newPanelElementPositions.push({ ++ element: c.id, ++ visible: c.visibleToggleBtn.get_active(), ++ position: c.positionCombo.get_active_id() ++ }); ++ }); ++ ++ monitors.forEach(m => panelElementPositionsSettings[m] = newPanelElementPositions); ++ this._settings.set_string('panel-element-positions', JSON.stringify(panelElementPositionsSettings)); ++ }; ++ ++ ++ labels[Pos.SHOW_APPS_BTN] = _('Show Applications button'); ++ labels[Pos.ACTIVITIES_BTN] = _('Activities button'); ++ labels[Pos.TASKBAR] = _('Taskbar'); ++ labels[Pos.DATE_MENU] = _('Date menu'); ++ labels[Pos.SYSTEM_MENU] = _('System menu'); ++ labels[Pos.LEFT_BOX] = _('Left box'); ++ labels[Pos.CENTER_BOX] = _('Center box'); ++ labels[Pos.RIGHT_BOX] = _('Right box'); ++ labels[Pos.DESKTOP_BTN] = _('Desktop button'); ++ ++ panelElementPositions.forEach(el => { ++ let row = new Gtk.ListBoxRow(); ++ let grid = new Gtk.Grid({ margin: 2, margin_left: 12, margin_right: 12, column_spacing: 8 }); ++ let upDownGrid = new Gtk.Grid({ column_spacing: 2 }); ++ let upBtn = new Gtk.Button({ tooltip_text: _('Move up') }); ++ let upImg = new Gtk.Image({ icon_name: 'go-up-symbolic', pixel_size: 12 }); ++ let downBtn = new Gtk.Button({ tooltip_text: _('Move down') }); ++ let downImg = new Gtk.Image({ icon_name: 'go-down-symbolic', pixel_size: 12 }); ++ let visibleToggleBtn = new Gtk.ToggleButton({ label: _('Visible'), active: el.visible }); ++ let positionCombo = new Gtk.ComboBoxText({ tooltip_text: _('Select element position') }); ++ let upDownClickHandler = limit => { ++ let index = row.get_index(); ++ ++ if (index != limit) { ++ taskbarListBox.remove(row); ++ taskbarListBox.insert(row, index + (!limit ? -1 : 1)); ++ updateElementsSettings(); ++ } ++ }; ++ ++ positionCombo.append(Pos.STACKED_TL, isVertical ? _('Stacked to top') : _('Stacked to left')); ++ positionCombo.append(Pos.STACKED_BR, isVertical ? _('Stacked to bottom') :_('Stacked to right')); ++ positionCombo.append(Pos.CENTERED, _('Centered')); ++ positionCombo.append(Pos.CENTERED_MONITOR, _('Monitor Center')); ++ positionCombo.set_active_id(el.position); ++ ++ upBtn.connect('clicked', () => upDownClickHandler(0)); ++ downBtn.connect('clicked', () => upDownClickHandler(panelElementPositions.length - 1)); ++ visibleToggleBtn.connect('toggled', () => updateElementsSettings()); ++ positionCombo.connect('changed', () => updateElementsSettings()); ++ ++ upBtn.add(upImg); ++ downBtn.add(downImg); ++ ++ upDownGrid.add(upBtn); ++ upDownGrid.add(downBtn); ++ ++ grid.add(upDownGrid); ++ grid.add(new Gtk.Label({ label: labels[el.element], xalign: 0, hexpand: true })); ++ ++ if (Pos.optionDialogFunctions[el.element]) { ++ let cogImg = new Gtk.Image({ icon_name: 'emblem-system-symbolic' }); ++ let optionsBtn = new Gtk.Button({ tooltip_text: _('More options') }); ++ ++ optionsBtn.get_style_context().add_class('circular'); ++ optionsBtn.add(cogImg); ++ grid.add(optionsBtn); ++ ++ optionsBtn.connect('clicked', () => this[Pos.optionDialogFunctions[el.element]]()); ++ } ++ ++ grid.add(visibleToggleBtn); ++ grid.add(positionCombo); ++ ++ row.id = el.element; ++ row.visibleToggleBtn = visibleToggleBtn; ++ row.positionCombo = positionCombo; ++ ++ row.add(grid); ++ taskbarListBox.add(row); ++ }); ++ ++ taskbarListBox.show_all(); ++ }, ++ ++ _showShowAppsButtonOptions: function() { ++ let dialog = new Gtk.Dialog({ title: _('Show Applications options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('show_applications_options'); ++ dialog.get_content_area().add(box); ++ ++ let fileChooser = this._builder.get_object('show_applications_icon_file_filebutton'); ++ let fileImage = this._builder.get_object('show_applications_current_icon_image'); ++ let fileFilter = new Gtk.FileFilter(); ++ let handleIconChange = function(newIconPath) { ++ if (newIconPath && GLib.file_test(newIconPath, GLib.FileTest.EXISTS)) { ++ let file = Gio.File.new_for_path(newIconPath) ++ let pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(file.read(null), 32, 32, true, null); ++ ++ fileImage.set_from_pixbuf(pixbuf); ++ fileChooser.set_filename(newIconPath); ++ } else { ++ newIconPath = ''; ++ fileImage.set_from_icon_name('view-app-grid-symbolic', 32); ++ fileChooser.unselect_all(); ++ fileChooser.set_current_folder(GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES)); ++ } ++ ++ this._settings.set_string('show-apps-icon-file', newIconPath || ''); ++ }; ++ ++ fileFilter.add_pixbuf_formats(); ++ fileChooser.filter = fileFilter; ++ ++ fileChooser.connect('file-set', widget => handleIconChange.call(this, widget.get_filename())); ++ handleIconChange.call(this, this._settings.get_string('show-apps-icon-file')); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('show-apps-icon-side-padding', this._settings.get_default_value('show-apps-icon-side-padding')); ++ this._builder.get_object('show_applications_side_padding_spinbutton').set_value(this._settings.get_int('show-apps-icon-side-padding')); ++ this._settings.set_value('show-apps-override-escape', this._settings.get_default_value('show-apps-override-escape')); ++ handleIconChange.call(this, null); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ }, ++ ++ _showDesktopButtonOptions: function() { ++ let dialog = new Gtk.Dialog({ title: _('Show Desktop options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_show_showdesktop_options'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width')); ++ this._builder.get_object('show_showdesktop_width_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('showdesktop-button-width', widget.get_value()); ++ })); ++ ++ this._builder.get_object('show_showdesktop_delay_spinbutton').set_value(this._settings.get_int('show-showdesktop-delay')); ++ this._builder.get_object('show_showdesktop_delay_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('show-showdesktop-delay', widget.get_value()); ++ })); ++ ++ this._builder.get_object('show_showdesktop_time_spinbutton').set_value(this._settings.get_int('show-showdesktop-time')); ++ this._builder.get_object('show_showdesktop_time_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('show-showdesktop-time', widget.get_value()); ++ })); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('showdesktop-button-width', this._settings.get_default_value('showdesktop-button-width')); ++ this._builder.get_object('show_showdesktop_width_spinbutton').set_value(this._settings.get_int('showdesktop-button-width')); ++ ++ this._settings.set_value('show-showdesktop-hover', this._settings.get_default_value('show-showdesktop-hover')); ++ ++ this._settings.set_value('show-showdesktop-delay', this._settings.get_default_value('show-showdesktop-delay')); ++ this._builder.get_object('show_showdesktop_delay_spinbutton').set_value(this._settings.get_int('show-showdesktop-delay')); ++ ++ this._settings.set_value('show-showdesktop-time', this._settings.get_default_value('show-showdesktop-time')); ++ this._builder.get_object('show_showdesktop_time_spinbutton').set_value(this._settings.get_int('show-showdesktop-time')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ }, ++ ++ _bindSettings: function() { ++ // size options ++ let panel_size_scale = this._builder.get_object('panel_size_scale'); ++ panel_size_scale.set_range(DEFAULT_PANEL_SIZES[DEFAULT_PANEL_SIZES.length - 1], DEFAULT_PANEL_SIZES[0]); ++ DEFAULT_PANEL_SIZES.slice(1, -1).forEach(function(val) { ++ panel_size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString()); ++ }); ++ ++ // Correct for rtl languages ++ if (this._rtl) { ++ // Flip value position: this is not done automatically ++ panel_size_scale.set_value_pos(Gtk.PositionType.LEFT); ++ // I suppose due to a bug, having a more than one mark and one above a value of 100 ++ // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable ++ // and then manually inverting it ++ panel_size_scale.set_flippable(false); ++ panel_size_scale.set_inverted(true); ++ } ++ ++ // Dots Position option ++ let dotPosition = this._settings.get_string('dot-position'); ++ ++ switch (dotPosition) { ++ case 'BOTTOM': ++ this._builder.get_object('dots_bottom_button').set_active(true); ++ break; ++ case 'TOP': ++ this._builder.get_object('dots_top_button').set_active(true); ++ break; ++ case 'LEFT': ++ this._builder.get_object('dots_left_button').set_active(true); ++ break; ++ case 'RIGHT': ++ this._builder.get_object('dots_right_button').set_active(true); ++ break; ++ } ++ ++ this._builder.get_object('dot_style_focused_combo').set_active_id(this._settings.get_string('dot-style-focused')); ++ this._builder.get_object('dot_style_focused_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('dot-style-focused', widget.get_active_id()); ++ })); ++ ++ this._builder.get_object('dot_style_unfocused_combo').set_active_id(this._settings.get_string('dot-style-unfocused')); ++ this._builder.get_object('dot_style_unfocused_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('dot-style-unfocused', widget.get_active_id()); ++ })); ++ ++ for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) { ++ let idx = i; ++ this._builder.get_object('dot_color_' + idx + '_colorbutton').connect('notify::color', Lang.bind(this, function(button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('dot-color-' + idx, hexString); ++ })); ++ ++ this._builder.get_object('dot_color_unfocused_' + idx + '_colorbutton').connect('notify::color', Lang.bind(this, function(button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('dot-color-unfocused-' + idx, hexString); ++ })); ++ } ++ ++ this._builder.get_object('dot_color_apply_all_button').connect('clicked', Lang.bind(this, function() { ++ for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) { ++ this._settings.set_value('dot-color-' + i, this._settings.get_value('dot-color-1')); ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('dot-color-' + i)); ++ this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba); ++ } ++ })); ++ ++ this._builder.get_object('dot_color_unfocused_apply_all_button').connect('clicked', Lang.bind(this, function() { ++ for (let i = 2; i <= MAX_WINDOW_INDICATOR; i++) { ++ this._settings.set_value('dot-color-unfocused-' + i, this._settings.get_value('dot-color-unfocused-1')); ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('dot-color-unfocused-' + i)); ++ this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba); ++ } ++ })); ++ ++ this._builder.get_object('focus_highlight_color_colorbutton').connect('notify::color', Lang.bind(this, function(button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('focus-highlight-color', hexString); ++ })); ++ ++ this._builder.get_object('dot_style_options_button').connect('clicked', Lang.bind(this, function() { ++ ++ let dialog = new Gtk.Dialog({ title: _('Running Indicator Options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_dots_options'); ++ dialog.get_content_area().add(box); ++ ++ this._settings.bind('dot-color-dominant', ++ this._builder.get_object('dot_color_dominant_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('dot-color-override', ++ this._builder.get_object('dot_color_override_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ // when either becomes active, turn the other off ++ this._builder.get_object('dot_color_dominant_switch').connect('state-set', Lang.bind (this, function(widget) { ++ if (widget.get_active()) this._settings.set_boolean('dot-color-override', false); ++ })); ++ this._builder.get_object('dot_color_override_switch').connect('state-set', Lang.bind (this, function(widget) { ++ if (widget.get_active()) this._settings.set_boolean('dot-color-dominant', false); ++ })); ++ ++ this._settings.bind('dot-color-unfocused-different', ++ this._builder.get_object('dot_color_unfocused_different_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('dot-color-override', ++ this._builder.get_object('grid_dot_color'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('dot-color-override', ++ this._builder.get_object('dot_color_unfocused_box'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('dot-color-unfocused-different', ++ this._builder.get_object('grid_dot_color_unfocused'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) { ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('dot-color-' + i)); ++ this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba); ++ ++ rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('dot-color-unfocused-' + i)); ++ this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba); ++ } ++ ++ this._settings.bind('focus-highlight', ++ this._builder.get_object('focus_highlight_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('focus-highlight', ++ this._builder.get_object('grid_focus_highlight_options'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('focus-highlight-dominant', ++ this._builder.get_object('focus_highlight_dominant_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('focus-highlight-dominant', ++ this._builder.get_object('focus_highlight_color_label'), ++ 'sensitive', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ ++ this._settings.bind('focus-highlight-dominant', ++ this._builder.get_object('focus_highlight_color_colorbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ ++ ++ (function() { ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('focus-highlight-color')); ++ this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba); ++ }).apply(this); ++ ++ this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity')); ++ this._builder.get_object('focus_highlight_opacity_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('focus-highlight-opacity', widget.get_value()); ++ })); ++ ++ this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size')); ++ this._builder.get_object('dot_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('dot-size', widget.get_value()); ++ })); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('dot-color-dominant', this._settings.get_default_value('dot-color-dominant')); ++ this._settings.set_value('dot-color-override', this._settings.get_default_value('dot-color-override')); ++ this._settings.set_value('dot-color-unfocused-different', this._settings.get_default_value('dot-color-unfocused-different')); ++ ++ this._settings.set_value('focus-highlight-color', this._settings.get_default_value('focus-highlight-color')); ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('focus-highlight-color')); ++ this._builder.get_object('focus_highlight_color_colorbutton').set_rgba(rgba); ++ ++ this._settings.set_value('focus-highlight-opacity', this._settings.get_default_value('focus-highlight-opacity')); ++ this._builder.get_object('focus_highlight_opacity_spinbutton').set_value(this._settings.get_int('focus-highlight-opacity')); ++ ++ for (let i = 1; i <= MAX_WINDOW_INDICATOR; i++) { ++ this._settings.set_value('dot-color-' + i, this._settings.get_default_value('dot-color-' + i)); ++ rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('dot-color-' + i)); ++ this._builder.get_object('dot_color_' + i + '_colorbutton').set_rgba(rgba); ++ ++ this._settings.set_value('dot-color-unfocused-' + i, this._settings.get_default_value('dot-color-unfocused-' + i)); ++ rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('dot-color-unfocused-' + i)); ++ this._builder.get_object('dot_color_unfocused_' + i + '_colorbutton').set_rgba(rgba); ++ } ++ ++ this._settings.set_value('dot-size', this._settings.get_default_value('dot-size')); ++ this._builder.get_object('dot_size_spinbutton').set_value(this._settings.get_int('dot-size')); ++ ++ this._settings.set_value('focus-highlight', this._settings.get_default_value('focus-highlight')); ++ this._settings.set_value('focus-highlight-dominant', this._settings.get_default_value('focus-highlight-dominant')); ++ ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ //multi-monitor ++ this.monitors = this._settings.get_value('available-monitors').deep_unpack(); ++ ++ let dtpPrimaryMonitorIndex = this.monitors.indexOf(this._settings.get_int('primary-monitor')); ++ ++ if (dtpPrimaryMonitorIndex < 0) { ++ dtpPrimaryMonitorIndex = 0; ++ } ++ ++ this._currentMonitorIndex = this.monitors[dtpPrimaryMonitorIndex]; ++ ++ this._settings.connect('changed::panel-positions', () => this._updateVerticalRelatedOptions()); ++ this._updateVerticalRelatedOptions(); ++ ++ for (let i = 0; i < this.monitors.length; ++i) { ++ //the primary index is the first one in the "available-monitors" setting ++ let label = !i ? _('Primary monitor') : _('Monitor ') + (i + 1); ++ ++ this._builder.get_object('multimon_primary_combo').append_text(label); ++ this._builder.get_object('taskbar_position_monitor_combo').append_text(label); ++ } ++ ++ this._builder.get_object('multimon_primary_combo').set_active(dtpPrimaryMonitorIndex); ++ this._builder.get_object('taskbar_position_monitor_combo').set_active(dtpPrimaryMonitorIndex); ++ ++ this._settings.bind('panel-element-positions-monitors-sync', ++ this._builder.get_object('taskbar_position_sync_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('panel-element-positions-monitors-sync', ++ this._builder.get_object('taskbar_position_monitor_combo'), ++ 'sensitive', ++ Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ ++ this._settings.connect('changed::panel-element-positions-monitors-sync', () => { ++ this._maybeDisableTopPosition(); ++ // The anchor combo box may has different labels for single- or all-monitor configuration. ++ this._setAnchorLabels(this._currentMonitorIndex); ++ }); ++ ++ this._builder.get_object('multimon_primary_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('primary-monitor', this.monitors[widget.get_active()]); ++ })); ++ ++ this._builder.get_object('taskbar_position_monitor_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._currentMonitorIndex = this.monitors[widget.get_active()]; ++ this._updateWidgetSettingsForMonitor(this._currentMonitorIndex); ++ })); ++ ++ this._settings.bind('multi-monitors', ++ this._builder.get_object('multimon_multi_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ if (this.monitors.length === 1) { ++ this._builder.get_object('multimon_multi_switch').set_sensitive(false); ++ } ++ ++ const panel_length_scale = this._builder.get_object('panel_length_scale'); ++ panel_length_scale.connect('value-changed', Lang.bind (this, function(widget) { ++ const value = widget.get_value(); ++ const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; ++ monitorsToSetFor.forEach(monitorIndex => { ++ PanelSettings.setPanelLength(this._settings, monitorIndex, value); ++ }); ++ ++ this._setAnchorWidgetSensitivity(value); ++ })); ++ ++ this._builder.get_object('panel_anchor_combo').connect('changed', Lang.bind (this, function(widget) { ++ const value = widget.get_active_id(); ++ // Value can be null while anchor labels are being swapped out ++ if (value !== null) { ++ const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; ++ monitorsToSetFor.forEach(monitorIndex => { ++ PanelSettings.setPanelAnchor(this._settings, monitorIndex, value); ++ }); ++ } ++ })); ++ ++ this._updateWidgetSettingsForMonitor(this._currentMonitorIndex); ++ ++ //dynamic opacity ++ this._settings.bind('trans-use-custom-bg', ++ this._builder.get_object('trans_bg_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('trans-use-custom-bg', ++ this._builder.get_object('trans_bg_color_colorbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('trans-bg-color')); ++ this._builder.get_object('trans_bg_color_colorbutton').set_rgba(rgba); ++ ++ this._builder.get_object('trans_bg_color_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('trans-bg-color', hexString); ++ })); ++ ++ this._settings.bind('trans-use-custom-opacity', ++ this._builder.get_object('trans_opacity_override_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('trans-use-custom-opacity', ++ this._builder.get_object('trans_opacity_box'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('trans_opacity_override_switch').connect('notify::active', (widget) => { ++ if (!widget.get_active()) ++ this._builder.get_object('trans_dyn_switch').set_active(false); ++ }); ++ ++ this._builder.get_object('trans_opacity_spinbutton').set_value(this._settings.get_double('trans-panel-opacity') * 100); ++ this._builder.get_object('trans_opacity_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_double('trans-panel-opacity', widget.get_value() * 0.01); ++ })); ++ ++ this._settings.bind('trans-use-dynamic-opacity', ++ this._builder.get_object('trans_dyn_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('trans-use-dynamic-opacity', ++ this._builder.get_object('trans_dyn_options_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('trans-dynamic-behavior', ++ this._builder.get_object('trans_options_window_type_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('trans-use-custom-gradient', ++ this._builder.get_object('trans_gradient_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('trans-use-custom-gradient', ++ this._builder.get_object('trans_gradient_box'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ rgba.parse(this._settings.get_string('trans-gradient-top-color')); ++ this._builder.get_object('trans_gradient_color1_colorbutton').set_rgba(rgba); ++ ++ this._builder.get_object('trans_gradient_color1_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('trans-gradient-top-color', hexString); ++ })); ++ ++ this._builder.get_object('trans_gradient_color1_spinbutton').set_value(this._settings.get_double('trans-gradient-top-opacity') * 100); ++ this._builder.get_object('trans_gradient_color1_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_double('trans-gradient-top-opacity', widget.get_value() * 0.01); ++ })); ++ ++ rgba.parse(this._settings.get_string('trans-gradient-bottom-color')); ++ this._builder.get_object('trans_gradient_color2_colorbutton').set_rgba(rgba); ++ ++ this._builder.get_object('trans_gradient_color2_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('trans-gradient-bottom-color', hexString); ++ })); ++ ++ this._builder.get_object('trans_gradient_color2_spinbutton').set_value(this._settings.get_double('trans-gradient-bottom-opacity') * 100); ++ this._builder.get_object('trans_gradient_color2_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_double('trans-gradient-bottom-opacity', widget.get_value() * 0.01); ++ })); ++ ++ this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance')); ++ this._builder.get_object('trans_options_distance_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_int('trans-dynamic-distance', widget.get_value()); ++ })); ++ ++ this._builder.get_object('trans_options_min_opacity_spinbutton').set_value(this._settings.get_double('trans-dynamic-anim-target') * 100); ++ this._builder.get_object('trans_options_min_opacity_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_double('trans-dynamic-anim-target', widget.get_value() * 0.01); ++ })); ++ ++ this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time')); ++ this._builder.get_object('trans_options_anim_time_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_int('trans-dynamic-anim-time', widget.get_value()); ++ })); ++ ++ this._builder.get_object('trans_dyn_options_button').connect('clicked', Lang.bind(this, function() { ++ let dialog = new Gtk.Dialog({ title: _('Dynamic opacity options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_dynamic_opacity_options'); ++ dialog.get_content_area().add(box); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('trans-dynamic-behavior', this._settings.get_default_value('trans-dynamic-behavior')); ++ ++ this._settings.set_value('trans-dynamic-distance', this._settings.get_default_value('trans-dynamic-distance')); ++ this._builder.get_object('trans_options_distance_spinbutton').set_value(this._settings.get_int('trans-dynamic-distance')); ++ ++ this._settings.set_value('trans-dynamic-anim-target', this._settings.get_default_value('trans-dynamic-anim-target')); ++ this._builder.get_object('trans_options_min_opacity_spinbutton').set_value(this._settings.get_double('trans-dynamic-anim-target') * 100); ++ ++ this._settings.set_value('trans-dynamic-anim-time', this._settings.get_default_value('trans-dynamic-anim-time')); ++ this._builder.get_object('trans_options_anim_time_spinbutton').set_value(this._settings.get_int('trans-dynamic-anim-time')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ this._settings.bind('desktop-line-use-custom-color', ++ this._builder.get_object('override_show_desktop_line_color_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('desktop-line-use-custom-color', ++ this._builder.get_object('override_show_desktop_line_color_colorbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ rgba.parse(this._settings.get_string('desktop-line-custom-color')); ++ this._builder.get_object('override_show_desktop_line_color_colorbutton').set_rgba(rgba); ++ this._builder.get_object('override_show_desktop_line_color_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ this._settings.set_string('desktop-line-custom-color', css); ++ })); ++ ++ ++ this._settings.bind('intellihide', ++ this._builder.get_object('intellihide_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide', ++ this._builder.get_object('intellihide_options_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-hide-from-windows', ++ this._builder.get_object('intellihide_window_hide_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-hide-from-windows', ++ this._builder.get_object('intellihide_behaviour_options'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-behaviour', ++ this._builder.get_object('intellihide_behaviour_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-use-pressure', ++ this._builder.get_object('intellihide_use_pressure_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-use-pressure', ++ this._builder.get_object('intellihide_use_pressure_options'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-show-in-fullscreen', ++ this._builder.get_object('intellihide_show_in_fullscreen_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('intellihide-only-secondary', ++ this._builder.get_object('intellihide_only_secondary_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('multi-monitors', ++ this._builder.get_object('grid_intellihide_only_secondary'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('multimon_multi_switch').connect('notify::active', (widget) => { ++ if (!widget.get_active()) ++ this._builder.get_object('intellihide_only_secondary_switch').set_active(false); ++ }); ++ ++ this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold')); ++ this._builder.get_object('intellihide_pressure_threshold_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_int('intellihide-pressure-threshold', widget.get_value()); ++ })); ++ ++ this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time')); ++ this._builder.get_object('intellihide_pressure_time_spinbutton').connect('value-changed', Lang.bind(this, function (widget) { ++ this._settings.set_int('intellihide-pressure-time', widget.get_value()); ++ })); ++ ++ this._settings.bind('intellihide-key-toggle-text', ++ this._builder.get_object('intellihide_toggle_entry'), ++ 'text', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.connect('changed::intellihide-key-toggle-text', () => setShortcut(this._settings, 'intellihide-key-toggle')); ++ ++ this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time')); ++ this._builder.get_object('intellihide_animation_time_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('intellihide-animation-time', widget.get_value()); ++ })); ++ ++ this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay')); ++ this._builder.get_object('intellihide_close_delay_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('intellihide-close-delay', widget.get_value()); ++ })); ++ ++ this._builder.get_object('intellihide_enable_start_delay_spinbutton').set_value(this._settings.get_int('intellihide-enable-start-delay')); ++ this._builder.get_object('intellihide_enable_start_delay_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('intellihide-enable-start-delay', widget.get_value()); ++ })); ++ ++ this._builder.get_object('intellihide_options_button').connect('clicked', Lang.bind(this, function() { ++ let dialog = new Gtk.Dialog({ title: _('Intellihide options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_intellihide_options'); ++ dialog.get_content_area().add(box); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('intellihide-hide-from-windows', this._settings.get_default_value('intellihide-hide-from-windows')); ++ this._settings.set_value('intellihide-behaviour', this._settings.get_default_value('intellihide-behaviour')); ++ this._settings.set_value('intellihide-use-pressure', this._settings.get_default_value('intellihide-use-pressure')); ++ this._settings.set_value('intellihide-show-in-fullscreen', this._settings.get_default_value('intellihide-show-in-fullscreen')); ++ this._settings.set_value('intellihide-only-secondary', this._settings.get_default_value('intellihide-only-secondary')); ++ ++ this._settings.set_value('intellihide-pressure-threshold', this._settings.get_default_value('intellihide-pressure-threshold')); ++ this._builder.get_object('intellihide_pressure_threshold_spinbutton').set_value(this._settings.get_int('intellihide-pressure-threshold')); ++ ++ this._settings.set_value('intellihide-pressure-time', this._settings.get_default_value('intellihide-pressure-time')); ++ this._builder.get_object('intellihide_pressure_time_spinbutton').set_value(this._settings.get_int('intellihide-pressure-time')); ++ ++ this._settings.set_value('intellihide-key-toggle-text', this._settings.get_default_value('intellihide-key-toggle-text')); ++ ++ this._settings.set_value('intellihide-animation-time', this._settings.get_default_value('intellihide-animation-time')); ++ this._builder.get_object('intellihide_animation_time_spinbutton').set_value(this._settings.get_int('intellihide-animation-time')); ++ ++ this._settings.set_value('intellihide-close-delay', this._settings.get_default_value('intellihide-close-delay')); ++ this._builder.get_object('intellihide_close_delay_spinbutton').set_value(this._settings.get_int('intellihide-close-delay')); ++ ++ this._settings.set_value('intellihide-enable-start-delay', this._settings.get_default_value('intellihide-enable-start-delay')); ++ this._builder.get_object('intellihide_enable_start_delay_spinbutton').set_value(this._settings.get_int('intellihide-enable-start-delay')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ // Behavior panel ++ ++ this._builder.get_object('show_applications_side_padding_spinbutton').set_value(this._settings.get_int('show-apps-icon-side-padding')); ++ this._builder.get_object('show_applications_side_padding_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('show-apps-icon-side-padding', widget.get_value()); ++ })); ++ ++ this._settings.bind('animate-show-apps', ++ this._builder.get_object('application_button_animation_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-apps-override-escape', ++ this._builder.get_object('show_applications_esc_key_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-showdesktop-hover', ++ this._builder.get_object('show_showdesktop_hide_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-showdesktop-hover', ++ this._builder.get_object('grid_show_showdesktop_hide_options'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-appmenu', ++ this._builder.get_object('show_appmenu_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-window-previews', ++ this._builder.get_object('show_window_previews_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-window-previews', ++ this._builder.get_object('show_window_previews_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-tooltip', ++ this._builder.get_object('show_tooltip_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-favorites', ++ this._builder.get_object('show_favorite_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-favorites-all-monitors', ++ this._builder.get_object('multimon_multi_show_favorites_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-favorites', ++ this._builder.get_object('multimon_multi_show_favorites_switch'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('show-running-apps', ++ this._builder.get_object('show_runnning_apps_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._setPreviewTitlePosition(); ++ ++ this._builder.get_object('grid_preview_title_font_color_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('window-preview-title-font-color', hexString); ++ })); ++ ++ this._builder.get_object('show_window_previews_button').connect('clicked', Lang.bind(this, function() { ++ ++ let dialog = new Gtk.Dialog({ title: _('Window preview options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let scrolledWindow = this._builder.get_object('box_window_preview_options'); ++ ++ adjustScrollableHeight(this._builder.get_object('viewport_window_preview_options'), scrolledWindow); ++ ++ dialog.get_content_area().add(scrolledWindow); ++ ++ this._builder.get_object('preview_timeout_spinbutton').set_value(this._settings.get_int('show-window-previews-timeout')); ++ this._builder.get_object('preview_timeout_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('show-window-previews-timeout', widget.get_value()); ++ })); ++ ++ this._settings.bind('preview-middle-click-close', ++ this._builder.get_object('preview_middle_click_close_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('window-preview-fixed-x', ++ this._builder.get_object('preview_aspect_ratio_x_fixed_togglebutton'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('window-preview-fixed-y', ++ this._builder.get_object('preview_aspect_ratio_y_fixed_togglebutton'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('preview-use-custom-opacity', ++ this._builder.get_object('preview_custom_opacity_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('preview-use-custom-opacity', ++ this._builder.get_object('preview_custom_opacity_spinbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('window-preview-use-custom-icon-size', ++ this._builder.get_object('preview_custom_icon_size_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('window-preview-use-custom-icon-size', ++ this._builder.get_object('preview_custom_icon_size_spinbutton'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('preview_custom_opacity_spinbutton').set_value(this._settings.get_int('preview-custom-opacity')); ++ this._builder.get_object('preview_custom_opacity_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('preview-custom-opacity', widget.get_value()); ++ })); ++ ++ this._settings.bind('peek-mode', ++ this._builder.get_object('peek_mode_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('peek-mode', ++ this._builder.get_object('grid_enter_peek_mode_timeout'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('peek-mode', ++ this._builder.get_object('grid_peek_mode_opacity'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('window-preview-show-title', ++ this._builder.get_object('preview_show_title_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('window-preview-show-title', ++ this._builder.get_object('grid_preview_custom_icon_size'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('window-preview-show-title', ++ this._builder.get_object('grid_preview_title_size'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('window-preview-show-title', ++ this._builder.get_object('grid_preview_title_weight'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('window-preview-show-title', ++ this._builder.get_object('grid_preview_title_font_color'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('enter_peek_mode_timeout_spinbutton').set_value(this._settings.get_int('enter-peek-mode-timeout')); ++ this._builder.get_object('enter_peek_mode_timeout_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('enter-peek-mode-timeout', widget.get_value()); ++ })); ++ ++ this._builder.get_object('leave_timeout_spinbutton').set_value(this._settings.get_int('leave-timeout')); ++ this._builder.get_object('leave_timeout_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('leave-timeout', widget.get_value()); ++ })); ++ ++ this._settings.bind('window-preview-hide-immediate-click', ++ this._builder.get_object('preview_immediate_click_button'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('animation_time_spinbutton').set_value(this._settings.get_int('window-preview-animation-time')); ++ this._builder.get_object('animation_time_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-animation-time', widget.get_value()); ++ })); ++ ++ this._builder.get_object('peek_mode_opacity_spinbutton').set_value(this._settings.get_int('peek-mode-opacity')); ++ this._builder.get_object('peek_mode_opacity_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('peek-mode-opacity', widget.get_value()); ++ })); ++ ++ this._builder.get_object('preview_size_spinbutton').set_value(this._settings.get_int('window-preview-size')); ++ this._builder.get_object('preview_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-size', widget.get_value()); ++ })); ++ ++ this._builder.get_object('preview_aspect_ratio_x_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-x').toString()); ++ this._builder.get_object('preview_aspect_ratio_x_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-aspect-ratio-x', parseInt(widget.get_active_id(), 10)); ++ })); ++ ++ this._builder.get_object('preview_aspect_ratio_y_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-y').toString()); ++ this._builder.get_object('preview_aspect_ratio_y_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-aspect-ratio-y', parseInt(widget.get_active_id(), 10)); ++ })); ++ ++ this._builder.get_object('preview_padding_spinbutton').set_value(this._settings.get_int('window-preview-padding')); ++ this._builder.get_object('preview_padding_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-padding', widget.get_value()); ++ })); ++ ++ this._builder.get_object('preview_title_size_spinbutton').set_value(this._settings.get_int('window-preview-title-font-size')); ++ this._builder.get_object('preview_title_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-title-font-size', widget.get_value()); ++ })); ++ ++ this._builder.get_object('preview_custom_icon_size_spinbutton').set_value(this._settings.get_int('window-preview-custom-icon-size')); ++ this._builder.get_object('preview_custom_icon_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('window-preview-custom-icon-size', widget.get_value()); ++ })); ++ ++ this._builder.get_object('grid_preview_title_weight_combo').set_active_id(this._settings.get_string('window-preview-title-font-weight')); ++ this._builder.get_object('grid_preview_title_weight_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('window-preview-title-font-weight', widget.get_active_id()); ++ })); ++ ++ (function() { ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('window-preview-title-font-color')); ++ this._builder.get_object('grid_preview_title_font_color_colorbutton').set_rgba(rgba); ++ }).apply(this); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('show-window-previews-timeout', this._settings.get_default_value('show-window-previews-timeout')); ++ this._builder.get_object('preview_timeout_spinbutton').set_value(this._settings.get_int('show-window-previews-timeout')); ++ ++ this._settings.set_value('leave-timeout', this._settings.get_default_value('leave-timeout')); ++ this._builder.get_object('leave_timeout_spinbutton').set_value(this._settings.get_int('leave-timeout')); ++ ++ this._settings.set_value('window-preview-hide-immediate-click', this._settings.get_default_value('window-preview-hide-immediate-click')); ++ ++ this._settings.set_value('window-preview-animation-time', this._settings.get_default_value('window-preview-animation-time')); ++ this._builder.get_object('animation_time_spinbutton').set_value(this._settings.get_int('window-preview-animation-time')); ++ ++ this._settings.set_value('preview-use-custom-opacity', this._settings.get_default_value('preview-use-custom-opacity')); ++ ++ this._settings.set_value('window-preview-use-custom-icon-size', this._settings.get_default_value('window-preview-use-custom-icon-size')); ++ ++ this._settings.set_value('preview-custom-opacity', this._settings.get_default_value('preview-custom-opacity')); ++ this._builder.get_object('preview_custom_opacity_spinbutton').set_value(this._settings.get_int('preview-custom-opacity')); ++ ++ this._settings.set_value('window-preview-title-position', this._settings.get_default_value('window-preview-title-position')); ++ this._setPreviewTitlePosition(); ++ ++ this._settings.set_value('peek-mode', this._settings.get_default_value('peek-mode')); ++ this._settings.set_value('window-preview-show-title', this._settings.get_default_value('window-preview-show-title')); ++ this._settings.set_value('enter-peek-mode-timeout', this._settings.get_default_value('enter-peek-mode-timeout')); ++ this._builder.get_object('enter_peek_mode_timeout_spinbutton').set_value(this._settings.get_int('enter-peek-mode-timeout')); ++ this._settings.set_value('peek-mode-opacity', this._settings.get_default_value('peek-mode-opacity')); ++ this._builder.get_object('peek_mode_opacity_spinbutton').set_value(this._settings.get_int('peek-mode-opacity')); ++ ++ this._settings.set_value('window-preview-size', this._settings.get_default_value('window-preview-size')); ++ this._builder.get_object('preview_size_spinbutton').set_value(this._settings.get_int('window-preview-size')); ++ ++ this._settings.set_value('window-preview-fixed-x', this._settings.get_default_value('window-preview-fixed-x')); ++ this._settings.set_value('window-preview-fixed-y', this._settings.get_default_value('window-preview-fixed-y')); ++ ++ this._settings.set_value('window-preview-aspect-ratio-x', this._settings.get_default_value('window-preview-aspect-ratio-x')); ++ this._builder.get_object('preview_aspect_ratio_x_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-x').toString()); ++ ++ this._settings.set_value('window-preview-aspect-ratio-y', this._settings.get_default_value('window-preview-aspect-ratio-y')); ++ this._builder.get_object('preview_aspect_ratio_y_combo').set_active_id(this._settings.get_int('window-preview-aspect-ratio-y').toString()); ++ ++ this._settings.set_value('window-preview-padding', this._settings.get_default_value('window-preview-padding')); ++ this._builder.get_object('preview_padding_spinbutton').set_value(this._settings.get_int('window-preview-padding')); ++ ++ this._settings.set_value('preview-middle-click-close', this._settings.get_default_value('preview-middle-click-close')); ++ ++ this._settings.set_value('window-preview-title-font-size', this._settings.get_default_value('window-preview-title-font-size')); ++ this._builder.get_object('preview_title_size_spinbutton').set_value(this._settings.get_int('window-preview-title-font-size')); ++ ++ this._settings.set_value('window-preview-custom-icon-size', this._settings.get_default_value('window-preview-custom-icon-size')); ++ this._builder.get_object('preview_custom_icon_size_spinbutton').set_value(this._settings.get_int('window-preview-custom-icon-size')); ++ ++ this._settings.set_value('window-preview-title-font-weight', this._settings.get_default_value('window-preview-title-font-weight')); ++ this._builder.get_object('grid_preview_title_weight_combo').set_active_id(this._settings.get_string('window-preview-title-font-weight')); ++ ++ this._settings.set_value('window-preview-title-font-color', this._settings.get_default_value('window-preview-title-font-color')); ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('window-preview-title-font-color')); ++ this._builder.get_object('grid_preview_title_font_color_colorbutton').set_rgba(rgba); ++ ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(scrolledWindow); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ this._settings.bind('isolate-workspaces', ++ this._builder.get_object('isolate_workspaces_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('isolate-monitors', ++ this._builder.get_object('multimon_multi_isolate_monitor_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('overview-click-to-exit', ++ this._builder.get_object('clicktoexit_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('group-apps', ++ this._builder.get_object('group_apps_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ ++ this._settings.bind('group-apps', ++ this._builder.get_object('show_group_apps_options_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.INVERT_BOOLEAN); ++ ++ this._builder.get_object('group_apps_label_font_color_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('group-apps-label-font-color', hexString); ++ })); ++ ++ this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').connect('notify::color', Lang.bind(this, function (button) { ++ let rgba = button.get_rgba(); ++ let css = rgba.to_string(); ++ let hexString = cssHexString(css); ++ this._settings.set_string('group-apps-label-font-color-minimized', hexString); ++ })); ++ ++ this._settings.bind('group-apps-use-fixed-width', ++ this._builder.get_object('group_apps_use_fixed_width_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('group-apps-underline-unfocused', ++ this._builder.get_object('group_apps_underline_unfocused_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('group-apps-use-launchers', ++ this._builder.get_object('group_apps_use_launchers_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('show_group_apps_options_button').connect('clicked', Lang.bind(this, function() { ++ let dialog = new Gtk.Dialog({ title: _('Ungrouped application options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_group_apps_options'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size')); ++ this._builder.get_object('group_apps_label_font_size_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('group-apps-label-font-size', widget.get_value()); ++ })); ++ ++ this._builder.get_object('group_apps_label_font_weight_combo').set_active_id(this._settings.get_string('group-apps-label-font-weight')); ++ this._builder.get_object('group_apps_label_font_weight_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('group-apps-label-font-weight', widget.get_active_id()); ++ })); ++ ++ (function() { ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('group-apps-label-font-color')); ++ this._builder.get_object('group_apps_label_font_color_colorbutton').set_rgba(rgba); ++ }).apply(this); ++ ++ (function() { ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('group-apps-label-font-color-minimized')); ++ this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').set_rgba(rgba); ++ }).apply(this); ++ ++ this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width')); ++ this._builder.get_object('group_apps_label_max_width_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('group-apps-label-max-width', widget.get_value()); ++ })); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('group-apps-label-font-size', this._settings.get_default_value('group-apps-label-font-size')); ++ this._builder.get_object('group_apps_label_font_size_spinbutton').set_value(this._settings.get_int('group-apps-label-font-size')); ++ ++ this._settings.set_value('group-apps-label-font-weight', this._settings.get_default_value('group-apps-label-font-weight')); ++ this._builder.get_object('group_apps_label_font_weight_combo').set_active_id(this._settings.get_string('group-apps-label-font-weight')); ++ ++ this._settings.set_value('group-apps-label-font-color', this._settings.get_default_value('group-apps-label-font-color')); ++ let rgba = new Gdk.RGBA(); ++ rgba.parse(this._settings.get_string('group-apps-label-font-color')); ++ this._builder.get_object('group_apps_label_font_color_colorbutton').set_rgba(rgba); ++ ++ this._settings.set_value('group-apps-label-font-color-minimized', this._settings.get_default_value('group-apps-label-font-color-minimized')); ++ let minimizedFontColor = new Gdk.RGBA(); ++ minimizedFontColor.parse(this._settings.get_string('group-apps-label-font-color-minimized')); ++ this._builder.get_object('group_apps_label_font_color_minimized_colorbutton').set_rgba(minimizedFontColor); ++ ++ this._settings.set_value('group-apps-label-max-width', this._settings.get_default_value('group-apps-label-max-width')); ++ this._builder.get_object('group_apps_label_max_width_spinbutton').set_value(this._settings.get_int('group-apps-label-max-width')); ++ ++ this._settings.set_value('group-apps-use-fixed-width', this._settings.get_default_value('group-apps-use-fixed-width')); ++ this._settings.set_value('group-apps-underline-unfocused', this._settings.get_default_value('group-apps-underline-unfocused')); ++ this._settings.set_value('group-apps-use-launchers', this._settings.get_default_value('group-apps-use-launchers')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ this._builder.get_object('click_action_combo').set_active_id(this._settings.get_string('click-action')); ++ this._builder.get_object('click_action_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('click-action', widget.get_active_id()); ++ })); ++ ++ this._builder.get_object('shift_click_action_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('shift-click-action', widget.get_active_id()); ++ })); ++ ++ this._builder.get_object('middle_click_action_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('middle-click-action', widget.get_active_id()); ++ })); ++ this._builder.get_object('shift_middle_click_action_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('shift-middle-click-action', widget.get_active_id()); ++ })); ++ ++ // Create dialog for middle-click options ++ this._builder.get_object('middle_click_options_button').connect('clicked', Lang.bind(this, function() { ++ ++ let dialog = new Gtk.Dialog({ title: _('Customize middle-click behavior'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_middle_click_options'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('shift_click_action_combo').set_active_id(this._settings.get_string('shift-click-action')); ++ ++ this._builder.get_object('middle_click_action_combo').set_active_id(this._settings.get_string('middle-click-action')); ++ ++ this._builder.get_object('shift_middle_click_action_combo').set_active_id(this._settings.get_string('shift-middle-click-action')); ++ ++ this._settings.bind('shift-click-action', ++ this._builder.get_object('shift_click_action_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('middle-click-action', ++ this._builder.get_object('middle_click_action_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('shift-middle-click-action', ++ this._builder.get_object('shift_middle_click_action_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings for the relevant keys ++ let keys = ['shift-click-action', 'middle-click-action', 'shift-middle-click-action']; ++ keys.forEach(function(val) { ++ this._settings.set_value(val, this._settings.get_default_value(val)); ++ }, this); ++ this._builder.get_object('shift_click_action_combo').set_active_id(this._settings.get_string('shift-click-action')); ++ this._builder.get_object('middle_click_action_combo').set_active_id(this._settings.get_string('middle-click-action')); ++ this._builder.get_object('shift_middle_click_action_combo').set_active_id(this._settings.get_string('shift-middle-click-action')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ this._builder.get_object('scroll_panel_combo').set_active_id(this._settings.get_string('scroll-panel-action')); ++ this._builder.get_object('scroll_panel_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('scroll-panel-action', widget.get_active_id()); ++ })); ++ ++ this._builder.get_object('scroll_icon_combo').set_active_id(this._settings.get_string('scroll-icon-action')); ++ this._builder.get_object('scroll_icon_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('scroll-icon-action', widget.get_active_id()); ++ })); ++ ++ // Create dialog for panel scroll options ++ this._builder.get_object('scroll_panel_options_button').connect('clicked', Lang.bind(this, function() { ++ let dialog = new Gtk.Dialog({ title: _('Customize panel scroll behavior'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('scroll_panel_options_box'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('scroll_panel_options_delay_spinbutton').set_value(this._settings.get_int('scroll-panel-delay')); ++ this._builder.get_object('scroll_panel_options_delay_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('scroll-panel-delay', widget.get_value()); ++ })); ++ ++ this._settings.bind('scroll-panel-show-ws-popup', ++ this._builder.get_object('scroll_panel_options_show_ws_popup_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('scroll-panel-delay', this._settings.get_default_value('scroll-panel-delay')); ++ this._builder.get_object('scroll_panel_options_delay_spinbutton').set_value(this._settings.get_int('scroll-panel-delay')); ++ ++ this._settings.set_value('scroll-panel-show-ws-popup', this._settings.get_default_value('scroll-panel-show-ws-popup')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ // Create dialog for icon scroll options ++ this._builder.get_object('scroll_icon_options_button').connect('clicked', Lang.bind(this, function() { ++ let dialog = new Gtk.Dialog({ title: _('Customize icon scroll behavior'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('scroll_icon_options_box'); ++ dialog.get_content_area().add(box); ++ ++ this._builder.get_object('scroll_icon_options_delay_spinbutton').set_value(this._settings.get_int('scroll-icon-delay')); ++ this._builder.get_object('scroll_icon_options_delay_spinbutton').connect('value-changed', Lang.bind (this, function(widget) { ++ this._settings.set_int('scroll-icon-delay', widget.get_value()); ++ })); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('scroll-icon-delay', this._settings.get_default_value('scroll-icon-delay')); ++ this._builder.get_object('scroll_icon_options_delay_spinbutton').set_value(this._settings.get_int('scroll-icon-delay')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ this._settings.bind('hot-keys', ++ this._builder.get_object('hot_keys_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.bind('hot-keys', ++ this._builder.get_object('overlay_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('overlay_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('hotkeys-overlay-combo', widget.get_active_id()); ++ })); ++ ++ this._settings.bind('shortcut-previews', ++ this._builder.get_object('shortcut_preview_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('shortcut_num_keys_combo').set_active_id(this._settings.get_string('shortcut-num-keys')); ++ this._builder.get_object('shortcut_num_keys_combo').connect('changed', Lang.bind (this, function(widget) { ++ this._settings.set_string('shortcut-num-keys', widget.get_active_id()); ++ })); ++ ++ this._settings.connect('changed::hotkey-prefix-text', Lang.bind(this, function() {checkHotkeyPrefix(this._settings);})); ++ ++ this._builder.get_object('hotkey_prefix_combo').set_active_id(this._settings.get_string('hotkey-prefix-text')); ++ ++ this._settings.bind('hotkey-prefix-text', ++ this._builder.get_object('hotkey_prefix_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._builder.get_object('overlay_combo').set_active_id(this._settings.get_string('hotkeys-overlay-combo')); ++ ++ this._settings.bind('hotkeys-overlay-combo', ++ this._builder.get_object('overlay_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('overlay-timeout', ++ this._builder.get_object('timeout_spinbutton'), ++ 'value', ++ Gio.SettingsBindFlags.DEFAULT); ++ if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY') { ++ this._builder.get_object('timeout_spinbutton').set_sensitive(false); ++ } ++ ++ this._settings.connect('changed::hotkeys-overlay-combo', Lang.bind(this, function() { ++ if (this._settings.get_string('hotkeys-overlay-combo') !== 'TEMPORARILY') ++ this._builder.get_object('timeout_spinbutton').set_sensitive(false); ++ else ++ this._builder.get_object('timeout_spinbutton').set_sensitive(true); ++ })); ++ ++ this._settings.bind('shortcut-text', ++ this._builder.get_object('shortcut_entry'), ++ 'text', ++ Gio.SettingsBindFlags.DEFAULT); ++ this._settings.connect('changed::shortcut-text', Lang.bind(this, function() {setShortcut(this._settings, 'shortcut');})); ++ ++ // Create dialog for number overlay options ++ this._builder.get_object('overlay_button').connect('clicked', Lang.bind(this, function() { ++ ++ let dialog = new Gtk.Dialog({ title: _('Advanced hotkeys options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_overlay_shortcut'); ++ dialog.get_content_area().add(box); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings for the relevant keys ++ let keys = ['hotkey-prefix-text', 'shortcut-text', 'hotkeys-overlay-combo', 'overlay-timeout', 'shortcut-previews']; ++ keys.forEach(function(val) { ++ this._settings.set_value(val, this._settings.get_default_value(val)); ++ }, this); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ // setup dialog for secondary menu options ++ this._builder.get_object('secondarymenu_options_button').connect('clicked', Lang.bind(this, function() { ++ ++ let dialog = new Gtk.Dialog({ title: _('Secondary Menu Options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_secondarymenu_options'); ++ dialog.get_content_area().add(box); ++ ++ this._settings.bind('secondarymenu-contains-appmenu', ++ this._builder.get_object('secondarymenu_appmenu_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('secondarymenu-contains-showdetails', ++ this._builder.get_object('secondarymenu_showdetails_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('secondarymenu-contains-appmenu', this._settings.get_default_value('secondarymenu-contains-appmenu')); ++ this._settings.set_value('secondarymenu-contains-showdetails', this._settings.get_default_value('secondarymenu-contains-showdetails')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ // setup dialog for advanced options ++ this._builder.get_object('button_advanced_options').connect('clicked', Lang.bind(this, function() { ++ ++ let dialog = new Gtk.Dialog({ title: _('Advanced Options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('box_advanced_options'); ++ dialog.get_content_area().add(box); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ // Fine-tune panel ++ ++ let sizeScales = [ ++ {objectName: 'tray_size_scale', valueName: 'tray-size', range: DEFAULT_FONT_SIZES }, ++ {objectName: 'leftbox_size_scale', valueName: 'leftbox-size', range: DEFAULT_FONT_SIZES }, ++ {objectName: 'appicon_margin_scale', valueName: 'appicon-margin', range: DEFAULT_MARGIN_SIZES }, ++ {objectName: 'appicon_padding_scale', valueName: 'appicon-padding', range: DEFAULT_MARGIN_SIZES }, ++ {objectName: 'tray_padding_scale', valueName: 'tray-padding', range: DEFAULT_PADDING_SIZES }, ++ {objectName: 'leftbox_padding_scale', valueName: 'leftbox-padding', range: DEFAULT_PADDING_SIZES }, ++ {objectName: 'statusicon_padding_scale', valueName: 'status-icon-padding', range: DEFAULT_PADDING_SIZES }, ++ {objectName: 'panel_length_scale', valueName: '', range: LENGTH_MARKS } ++ ]; ++ ++ for(var idx in sizeScales) { ++ let size_scale = this._builder.get_object(sizeScales[idx].objectName); ++ let range = sizeScales[idx].range; ++ size_scale.set_range(range[range.length - 1], range[0]); ++ let value; ++ if (sizeScales[idx].objectName === 'panel_length_scale') { ++ value = PanelSettings.getPanelLength(this._settings, this._currentMonitorIndex); ++ } else { ++ value = this._settings.get_int(sizeScales[idx].valueName); ++ } ++ size_scale.set_value(value); ++ // Add marks from range arrays, omitting the first and last values. ++ range.slice(1, -1).forEach(function(val) { ++ size_scale.add_mark(val, Gtk.PositionType.TOP, val.toString()); ++ }); ++ ++ // Corrent for rtl languages ++ if (this._rtl) { ++ // Flip value position: this is not done automatically ++ size_scale.set_value_pos(Gtk.PositionType.LEFT); ++ // I suppose due to a bug, having a more than one mark and one above a value of 100 ++ // makes the rendering of the marks wrong in rtl. This doesn't happen setting the scale as not flippable ++ // and then manually inverting it ++ size_scale.set_flippable(false); ++ size_scale.set_inverted(true); ++ } ++ } ++ ++ this._settings.bind('animate-app-switch', ++ this._builder.get_object('animate_app_switch_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('animate-window-launch', ++ this._builder.get_object('animate_window_launch_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('animate-appicon-hover', ++ this._builder.get_object('animate_appicon_hover_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('animate-appicon-hover', ++ this._builder.get_object('animate_appicon_hover_button'), ++ 'sensitive', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ { ++ this._settings.bind('animate-appicon-hover-animation-type', ++ this._builder.get_object('animate_appicon_hover_options_type_combo'), ++ 'active-id', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ let scales = [ ++ ['animate_appicon_hover_options_duration_scale', 'animate-appicon-hover-animation-duration', 1], ++ ['animate_appicon_hover_options_rotation_scale', 'animate-appicon-hover-animation-rotation', 1], ++ ['animate_appicon_hover_options_travel_scale', 'animate-appicon-hover-animation-travel', 100], ++ ['animate_appicon_hover_options_zoom_scale', 'animate-appicon-hover-animation-zoom', 100], ++ ['animate_appicon_hover_options_convexity_scale', 'animate-appicon-hover-animation-convexity', 1], ++ ['animate_appicon_hover_options_extent_scale', 'animate-appicon-hover-animation-extent', 1], ++ ]; ++ ++ let updateScale = scale => { ++ let [id, key, factor] = scale; ++ let type = this._settings.get_string('animate-appicon-hover-animation-type'); ++ let value = this._settings.get_value(key).deep_unpack()[type]; ++ let defaultValue = this._settings.get_default_value(key).deep_unpack()[type]; ++ this._builder.get_object(id).sensitive = defaultValue !== undefined; ++ this._builder.get_object(id).set_value(value * factor || 0); ++ this._builder.get_object(id).clear_marks(); ++ this._builder.get_object(id).add_mark(defaultValue * factor, Gtk.PositionType.TOP, ++ defaultValue !== undefined ? (defaultValue * factor).toString() : ' '); ++ }; ++ ++ scales.forEach(scale => { ++ let [id, key, factor] = scale; ++ this._settings.connect('changed::' + key, () => updateScale(scale)); ++ this._builder.get_object(id).connect('value-changed', widget => { ++ let type = this._settings.get_string('animate-appicon-hover-animation-type'); ++ let variant = this._settings.get_value(key); ++ let unpacked = variant.deep_unpack(); ++ if (unpacked[type] != widget.get_value() / factor) { ++ unpacked[type] = widget.get_value() / factor; ++ this._settings.set_value(key, new GLib.Variant(variant.get_type_string(), unpacked)); ++ } ++ }); ++ }); ++ ++ this._settings.connect('changed::animate-appicon-hover-animation-type', () => scales.forEach(updateScale)); ++ scales.forEach(updateScale); ++ } ++ ++ this._builder.get_object('animate_appicon_hover_button').connect('clicked', Lang.bind(this, function() { ++ let dialog = new Gtk.Dialog({ title: _('App icon animation options'), ++ transient_for: this.widget.get_toplevel(), ++ use_header_bar: true, ++ modal: true }); ++ ++ // GTK+ leaves positive values for application-defined response ids. ++ // Use +1 for the reset action ++ dialog.add_button(_('Reset to defaults'), 1); ++ ++ let box = this._builder.get_object('animate_appicon_hover_options'); ++ dialog.get_content_area().add(box); ++ ++ dialog.connect('response', Lang.bind(this, function(dialog, id) { ++ if (id == 1) { ++ // restore default settings ++ this._settings.set_value('animate-appicon-hover-animation-type', this._settings.get_default_value('animate-appicon-hover-animation-type')); ++ this._settings.set_value('animate-appicon-hover-animation-duration', this._settings.get_default_value('animate-appicon-hover-animation-duration')); ++ this._settings.set_value('animate-appicon-hover-animation-rotation', this._settings.get_default_value('animate-appicon-hover-animation-rotation')); ++ this._settings.set_value('animate-appicon-hover-animation-travel', this._settings.get_default_value('animate-appicon-hover-animation-travel')); ++ this._settings.set_value('animate-appicon-hover-animation-zoom', this._settings.get_default_value('animate-appicon-hover-animation-zoom')); ++ this._settings.set_value('animate-appicon-hover-animation-convexity', this._settings.get_default_value('animate-appicon-hover-animation-convexity')); ++ this._settings.set_value('animate-appicon-hover-animation-extent', this._settings.get_default_value('animate-appicon-hover-animation-extent')); ++ } else { ++ // remove the settings box so it doesn't get destroyed; ++ dialog.get_content_area().remove(box); ++ dialog.destroy(); ++ } ++ return; ++ })); ++ ++ dialog.show_all(); ++ ++ })); ++ ++ this._settings.bind('stockgs-keep-dash', ++ this._builder.get_object('stockgs_dash_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('stockgs-keep-top-panel', ++ this._builder.get_object('stockgs_top_panel_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ ++ ++ this._settings.connect('changed::stockgs-keep-top-panel', () => this._maybeDisableTopPosition()); ++ ++ this._maybeDisableTopPosition(); ++ ++ this._settings.bind('stockgs-panelbtn-click-only', ++ this._builder.get_object('stockgs_panelbtn_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ this._settings.bind('stockgs-force-hotcorner', ++ this._builder.get_object('stockgs_hotcorner_switch'), ++ 'active', ++ Gio.SettingsBindFlags.DEFAULT); ++ ++ // About Panel ++ ++ this._builder.get_object('extension_version').set_label(Me.metadata.version.toString() + (Me.metadata.commit ? ' (' + Me.metadata.commit + ')' : '')); ++ ++ this._builder.get_object('importexport_export_button').connect('clicked', widget => { ++ this._showFileChooser( ++ _('Export settings'), ++ { action: Gtk.FileChooserAction.SAVE, ++ do_overwrite_confirmation: true }, ++ Gtk.STOCK_SAVE, ++ filename => { ++ let file = Gio.file_new_for_path(filename); ++ let raw = file.replace(null, false, Gio.FileCreateFlags.NONE, null); ++ let out = Gio.BufferedOutputStream.new_sized(raw, 4096); ++ ++ out.write_all(GLib.spawn_command_line_sync('dconf dump ' + SCHEMA_PATH)[1], null); ++ out.close(null); ++ } ++ ); ++ }); ++ ++ this._builder.get_object('importexport_import_button').connect('clicked', widget => { ++ this._showFileChooser( ++ _('Import settings'), ++ { action: Gtk.FileChooserAction.OPEN }, ++ Gtk.STOCK_OPEN, ++ filename => { ++ let settingsFile = Gio.File.new_for_path(filename); ++ let [ , pid, stdin, stdout, stderr] = ++ GLib.spawn_async_with_pipes( ++ null, ++ ['dconf', 'load', SCHEMA_PATH], ++ null, ++ GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, ++ null ++ ); ++ ++ stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true }); ++ GLib.close(stdout); ++ GLib.close(stderr); ++ ++ let [ , , , retCode] = GLib.spawn_command_line_sync(GSET + ' -d ' + Me.uuid); ++ ++ if (retCode == 0) { ++ GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, () => GLib.spawn_command_line_sync(GSET + ' -e ' + Me.uuid)); ++ } ++ ++ stdin.splice(settingsFile.read(null), Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | Gio.OutputStreamSpliceFlags.CLOSE_TARGET, null); ++ } ++ ); ++ }); ++ ++ }, ++ ++ _setPreviewTitlePosition: function() { ++ switch (this._settings.get_string('window-preview-title-position')) { ++ case 'BOTTOM': ++ this._builder.get_object('preview_title_position_bottom_button').set_active(true); ++ break; ++ case 'TOP': ++ this._builder.get_object('preview_title_position_top_button').set_active(true); ++ break; ++ } ++ }, ++ ++ _showFileChooser: function(title, params, acceptBtn, acceptHandler) { ++ let dialog = new Gtk.FileChooserDialog(mergeObjects({ title: title, transient_for: this.widget.get_toplevel() }, params)); ++ ++ dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL); ++ dialog.add_button(acceptBtn, Gtk.ResponseType.ACCEPT); ++ ++ if (dialog.run() == Gtk.ResponseType.ACCEPT) { ++ try { ++ acceptHandler(dialog.get_filename()); ++ } catch(e) { ++ log('error from dash-to-panel filechooser: ' + e); ++ } ++ } ++ ++ dialog.destroy(); ++ }, ++ ++ /** ++ * Object containing all signals defined in the glade file ++ */ ++ _SignalHandler: { ++ animate_appicon_hover_options_duration_scale_format_value_cb: function(scale, value) { ++ return _("%d ms").format(value); ++ }, ++ ++ animate_appicon_hover_options_rotation_scale_format_value_cb: function(scale, value) { ++ return _("%d °").format(value); ++ }, ++ ++ animate_appicon_hover_options_travel_scale_format_value_cb: function(scale, value) { ++ return _("%d %%").format(value); ++ }, ++ ++ animate_appicon_hover_options_zoom_scale_format_value_cb: function(scale, value) { ++ return _("%d %%").format(value); ++ }, ++ ++ animate_appicon_hover_options_convexity_scale_format_value_cb: function(scale, value) { ++ return _("%.1f").format(value); ++ }, ++ ++ animate_appicon_hover_options_extent_scale_format_value_cb: function(scale, value) { ++ return Gettext.ngettext("%d icon", "%d icons", value).format(value); ++ }, ++ ++ position_bottom_button_clicked_cb: function(button) { ++ if (!this._ignorePositionRadios && button.get_active()) this._setPanelPosition(Pos.BOTTOM); ++ }, ++ ++ position_top_button_clicked_cb: function(button) { ++ if (!this._ignorePositionRadios && button.get_active()) this._setPanelPosition(Pos.TOP); ++ }, ++ ++ position_left_button_clicked_cb: function(button) { ++ if (!this._ignorePositionRadios && button.get_active()) this._setPanelPosition(Pos.LEFT); ++ }, ++ ++ position_right_button_clicked_cb: function(button) { ++ if (!this._ignorePositionRadios && button.get_active()) this._setPanelPosition(Pos.RIGHT); ++ }, ++ ++ dots_bottom_button_toggled_cb: function(button) { ++ if (button.get_active()) ++ this._settings.set_string('dot-position', "BOTTOM"); ++ }, ++ ++ dots_top_button_toggled_cb: function(button) { ++ if (button.get_active()) ++ this._settings.set_string('dot-position', "TOP"); ++ }, ++ ++ dots_left_button_toggled_cb: function(button) { ++ if (button.get_active()) ++ this._settings.set_string('dot-position', "LEFT"); ++ }, ++ ++ dots_right_button_toggled_cb: function(button) { ++ if (button.get_active()) ++ this._settings.set_string('dot-position', "RIGHT"); ++ }, ++ ++ preview_title_position_bottom_button_toggled_cb: function(button) { ++ if (button.get_active()) ++ this._settings.set_string('window-preview-title-position', 'BOTTOM'); ++ }, ++ ++ preview_title_position_top_button_toggled_cb: function(button) { ++ if (button.get_active()) ++ this._settings.set_string('window-preview-title-position', 'TOP'); ++ }, ++ ++ ++ panel_length_scale_format_value_cb: function(scale, value) { ++ return value+ '%'; ++ }, ++ ++ panel_size_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ panel_size_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size continuously ++ if (this._panel_size_timeout > 0) ++ Mainloop.source_remove(this._panel_size_timeout); ++ ++ this._panel_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ const value = scale.get_value(); ++ const monitorSync = this._settings.get_boolean('panel-element-positions-monitors-sync'); ++ const monitorsToSetFor = monitorSync ? this.monitors : [this._currentMonitorIndex]; ++ monitorsToSetFor.forEach(monitorIndex => { ++ PanelSettings.setPanelSize(this._settings, monitorIndex, value); ++ }); ++ ++ this._panel_size_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ tray_size_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ tray_size_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._tray_size_timeout > 0) ++ Mainloop.source_remove(this._tray_size_timeout); ++ ++ this._tray_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('tray-size', scale.get_value()); ++ this._tray_size_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ leftbox_size_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ leftbox_size_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._leftbox_size_timeout > 0) ++ Mainloop.source_remove(this._leftbox_size_timeout); ++ ++ this._leftbox_size_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('leftbox-size', scale.get_value()); ++ this._leftbox_size_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ appicon_margin_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ appicon_margin_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._appicon_margin_timeout > 0) ++ Mainloop.source_remove(this._appicon_margin_timeout); ++ ++ this._appicon_margin_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('appicon-margin', scale.get_value()); ++ this._appicon_margin_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ appicon_padding_scale_format_value_cb: function(scale, value) { ++ return value + ' px'; ++ }, ++ ++ appicon_padding_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._appicon_padding_timeout > 0) ++ Mainloop.source_remove(this._appicon_padding_timeout); ++ ++ this._appicon_padding_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('appicon-padding', scale.get_value()); ++ this._appicon_padding_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ tray_padding_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ tray_padding_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._tray_padding_timeout > 0) ++ Mainloop.source_remove(this._tray_padding_timeout); ++ ++ this._tray_padding_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('tray-padding', scale.get_value()); ++ this._tray_padding_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ statusicon_padding_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ statusicon_padding_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._statusicon_padding_timeout > 0) ++ Mainloop.source_remove(this._statusicon_padding_timeout); ++ ++ this._statusicon_padding_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('status-icon-padding', scale.get_value()); ++ this._statusicon_padding_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ }, ++ ++ leftbox_padding_scale_format_value_cb: function(scale, value) { ++ return value+ ' px'; ++ }, ++ ++ leftbox_padding_scale_value_changed_cb: function(scale) { ++ // Avoid settings the size consinuosly ++ if (this._leftbox_padding_timeout > 0) ++ Mainloop.source_remove(this._leftbox_padding_timeout); ++ ++ this._leftbox_padding_timeout = Mainloop.timeout_add(SCALE_UPDATE_TIMEOUT, Lang.bind(this, function() { ++ this._settings.set_int('leftbox-padding', scale.get_value()); ++ this._leftbox_padding_timeout = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ } ++ } ++}); ++ ++function init() { ++ Convenience.initTranslations(); ++} ++ ++function buildPrefsWidget() { ++ let settings = new Settings(); ++ let widget = settings.widget; ++ ++ // I'd like the scrolled window to default to a size large enough to show all without scrolling, if it fits on the screen ++ // But, it doesn't seem possible, so I'm setting a minimum size if there seems to be enough screen real estate ++ widget.show_all(); ++ adjustScrollableHeight(settings.viewport, widget); ++ ++ return widget; ++} ++ ++function adjustScrollableHeight(viewport, scrollableWindow) { ++ let viewportSize = viewport.size_request(); ++ let screenHeight = scrollableWindow.get_screen().get_height() - 120; ++ ++ scrollableWindow.set_size_request(viewportSize.width, viewportSize.height > screenHeight ? screenHeight : viewportSize.height); ++} +diff --git a/extensions/dash-to-panel/progress.js b/extensions/dash-to-panel/progress.js +new file mode 100644 +index 00000000..1e84e82d +--- /dev/null ++++ b/extensions/dash-to-panel/progress.js +@@ -0,0 +1,598 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ */ ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Gio = imports.gi.Gio; ++const Cairo = imports.cairo; ++const Clutter = imports.gi.Clutter; ++const Pango = imports.gi.Pango; ++const St = imports.gi.St; ++const Signals = imports.signals; ++const Utils = Me.imports.utils; ++ ++ ++var ProgressManager = Utils.defineClass({ ++ Name: 'DashToPanel.ProgressManager', ++ ++ _init: function() { ++ ++ this._entriesByDBusName = {}; ++ ++ this._launcher_entry_dbus_signal_id = ++ Gio.DBus.session.signal_subscribe(null, // sender ++ 'com.canonical.Unity.LauncherEntry', // iface ++ null, // member ++ null, // path ++ null, // arg0 ++ Gio.DBusSignalFlags.NONE, ++ this._onEntrySignalReceived.bind(this)); ++ ++ this._dbus_name_owner_changed_signal_id = ++ Gio.DBus.session.signal_subscribe('org.freedesktop.DBus', // sender ++ 'org.freedesktop.DBus', // interface ++ 'NameOwnerChanged', // member ++ '/org/freedesktop/DBus', // path ++ null, // arg0 ++ Gio.DBusSignalFlags.NONE, ++ this._onDBusNameOwnerChanged.bind(this)); ++ ++ this._acquireUnityDBus(); ++ }, ++ ++ destroy: function() { ++ if (this._launcher_entry_dbus_signal_id) { ++ Gio.DBus.session.signal_unsubscribe(this._launcher_entry_dbus_signal_id); ++ } ++ ++ if (this._dbus_name_owner_changed_signal_id) { ++ Gio.DBus.session.signal_unsubscribe(this._dbus_name_owner_changed_signal_id); ++ } ++ ++ this._releaseUnityDBus(); ++ }, ++ ++ size: function() { ++ return Object.keys(this._entriesByDBusName).length; ++ }, ++ ++ lookupByDBusName: function(dbusName) { ++ return this._entriesByDBusName.hasOwnProperty(dbusName) ? this._entriesByDBusName[dbusName] : null; ++ }, ++ ++ lookupById: function(appId) { ++ let ret = []; ++ for (let dbusName in this._entriesByDBusName) { ++ let entry = this._entriesByDBusName[dbusName]; ++ if (entry && entry.appId() == appId) { ++ ret.push(entry); ++ } ++ } ++ ++ return ret; ++ }, ++ ++ addEntry: function(entry) { ++ let existingEntry = this.lookupByDBusName(entry.dbusName()); ++ if (existingEntry) { ++ existingEntry.update(entry); ++ } else { ++ this._entriesByDBusName[entry.dbusName()] = entry; ++ this.emit('progress-entry-added', entry); ++ } ++ }, ++ ++ removeEntry: function(entry) { ++ delete this._entriesByDBusName[entry.dbusName()] ++ this.emit('progress-entry-removed', entry); ++ }, ++ ++ _acquireUnityDBus: function() { ++ if (!this._unity_bus_id) { ++ Gio.DBus.session.own_name('com.canonical.Unity', ++ Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null); ++ } ++ }, ++ ++ _releaseUnityDBus: function() { ++ if (this._unity_bus_id) { ++ Gio.DBus.session.unown_name(this._unity_bus_id); ++ this._unity_bus_id = 0; ++ } ++ }, ++ ++ _onEntrySignalReceived: function(connection, sender_name, object_path, ++ interface_name, signal_name, parameters, user_data) { ++ if (!parameters || !signal_name) ++ return; ++ ++ if (signal_name == 'Update') { ++ if (!sender_name) { ++ return; ++ } ++ ++ this._handleUpdateRequest(sender_name, parameters); ++ } ++ }, ++ ++ _onDBusNameOwnerChanged: function(connection, sender_name, object_path, ++ interface_name, signal_name, parameters, user_data) { ++ if (!parameters || !this.size()) ++ return; ++ ++ let [name, before, after] = parameters.deep_unpack(); ++ ++ if (!after) { ++ if (this._entriesByDBusName.hasOwnProperty(before)) { ++ this.removeEntry(this._entriesByDBusName[before]); ++ } ++ } ++ }, ++ ++ _handleUpdateRequest: function(senderName, parameters) { ++ if (!senderName || !parameters) { ++ return; ++ } ++ ++ let [appUri, properties] = parameters.deep_unpack(); ++ let appId = appUri.replace(/(^\w+:|^)\/\//, ''); ++ let entry = this.lookupByDBusName(senderName); ++ ++ if (entry) { ++ entry.setDBusName(senderName); ++ entry.update(properties); ++ } else { ++ let entry = new AppProgress(senderName, appId, properties); ++ this.addEntry(entry); ++ } ++ } ++}); ++Signals.addSignalMethods(ProgressManager.prototype); ++ ++var AppProgress = Utils.defineClass({ ++ Name: 'DashToPanel.AppProgress', ++ ++ _init: function(dbusName, appId, properties) { ++ this._dbusName = dbusName; ++ this._appId = appId; ++ this._count = 0; ++ this._countVisible = false; ++ this._progress = 0.0; ++ this._progressVisible = false; ++ this._urgent = false; ++ this.update(properties); ++ }, ++ ++ appId: function() { ++ return this._appId; ++ }, ++ ++ dbusName: function() { ++ return this._dbusName; ++ }, ++ ++ count: function() { ++ return this._count; ++ }, ++ ++ setCount: function(count) { ++ if (this._count != count) { ++ this._count = count; ++ this.emit('count-changed', this._count); ++ } ++ }, ++ ++ countVisible: function() { ++ return this._countVisible; ++ }, ++ ++ setCountVisible: function(countVisible) { ++ if (this._countVisible != countVisible) { ++ this._countVisible = countVisible; ++ this.emit('count-visible-changed', this._countVisible); ++ } ++ }, ++ ++ progress: function() { ++ return this._progress; ++ }, ++ ++ setProgress: function(progress) { ++ if (this._progress != progress) { ++ this._progress = progress; ++ this.emit('progress-changed', this._progress); ++ } ++ }, ++ ++ progressVisible: function() { ++ return this._progressVisible; ++ }, ++ ++ setProgressVisible: function(progressVisible) { ++ if (this._progressVisible != progressVisible) { ++ this._progressVisible = progressVisible; ++ this.emit('progress-visible-changed', this._progressVisible); ++ } ++ }, ++ ++ urgent: function() { ++ return this._urgent; ++ }, ++ ++ setUrgent: function(urgent) { ++ if (this._urgent != urgent) { ++ this._urgent = urgent; ++ this.emit('urgent-changed', this._urgent); ++ } ++ }, ++ ++ setDBusName: function(dbusName) { ++ if (this._dbusName != dbusName) { ++ let oldName = this._dbusName; ++ this._dbusName = dbusName; ++ this.emit('dbus-name-changed', oldName); ++ } ++ }, ++ ++ update: function(other) { ++ if (other instanceof AppProgress) { ++ this.setDBusName(other.dbusName()) ++ this.setCount(other.count()); ++ this.setCountVisible(other.countVisible()); ++ this.setProgress(other.progress()); ++ this.setProgressVisible(other.progressVisible()) ++ this.setUrgent(other.urgent()); ++ } else { ++ for (let property in other) { ++ if (other.hasOwnProperty(property)) { ++ if (property == 'count') { ++ this.setCount(other[property].get_int64()); ++ } else if (property == 'count-visible') { ++ this.setCountVisible(Me.settings.get_boolean('progress-show-count') && other[property].get_boolean()); ++ } else if (property == 'progress') { ++ this.setProgress(other[property].get_double()); ++ } else if (property == 'progress-visible') { ++ this.setProgressVisible(Me.settings.get_boolean('progress-show-bar') && other[property].get_boolean()); ++ } else if (property == 'urgent') { ++ this.setUrgent(other[property].get_boolean()); ++ } else { ++ // Not implemented yet ++ } ++ } ++ } ++ } ++ } ++}); ++Signals.addSignalMethods(AppProgress.prototype); ++ ++ ++var ProgressIndicator = Utils.defineClass({ ++ Name: 'DashToPanel.ProgressIndicator', ++ ++ _init: function(source, progressManager) { ++ this._source = source; ++ this._progressManager = progressManager; ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this._sourceDestroyId = this._source.actor.connect('destroy', () => { ++ this._signalsHandler.destroy(); ++ }); ++ ++ this._notificationBadgeLabel = new St.Label({ style_class: 'badge' }); ++ this._notificationBadgeBin = new St.Bin({ ++ child: this._notificationBadgeLabel, y: 2, x: 2 ++ }); ++ this._notificationBadgeLabel.add_style_class_name('notification-badge'); ++ this._notificationBadgeCount = 0; ++ this._notificationBadgeBin.hide(); ++ ++ this._source._dtpIconContainer.add_child(this._notificationBadgeBin); ++ this._source._dtpIconContainer.connect('notify::allocation', this.updateNotificationBadge.bind(this)); ++ ++ this._progressManagerEntries = []; ++ this._progressManager.lookupById(this._source.app.id).forEach( ++ (entry) => { ++ this.insertEntry(entry); ++ } ++ ); ++ ++ this._signalsHandler.add([ ++ this._progressManager, ++ 'progress-entry-added', ++ this._onEntryAdded.bind(this) ++ ], [ ++ this._progressManager, ++ 'progress-entry-removed', ++ this._onEntryRemoved.bind(this) ++ ]); ++ }, ++ ++ destroy: function() { ++ this._source.actor.disconnect(this._sourceDestroyId); ++ this._signalsHandler.destroy(); ++ }, ++ ++ _onEntryAdded: function(appProgress, entry) { ++ if (!entry || !entry.appId()) ++ return; ++ if (this._source && this._source.app && this._source.app.id == entry.appId()) { ++ this.insertEntry(entry); ++ } ++ }, ++ ++ _onEntryRemoved: function(appProgress, entry) { ++ if (!entry || !entry.appId()) ++ return; ++ ++ if (this._source && this._source.app && this._source.app.id == entry.appId()) { ++ this.removeEntry(entry); ++ } ++ }, ++ ++ updateNotificationBadge: function() { ++ this._source.updateNumberOverlay(this._notificationBadgeBin); ++ this._notificationBadgeLabel.clutter_text.ellipsize = Pango.EllipsizeMode.MIDDLE; ++ }, ++ ++ _notificationBadgeCountToText: function(count) { ++ if (count <= 9999) { ++ return count.toString(); ++ } else if (count < 1e5) { ++ let thousands = count / 1e3; ++ return thousands.toFixed(1).toString() + "k"; ++ } else if (count < 1e6) { ++ let thousands = count / 1e3; ++ return thousands.toFixed(0).toString() + "k"; ++ } else if (count < 1e8) { ++ let millions = count / 1e6; ++ return millions.toFixed(1).toString() + "M"; ++ } else if (count < 1e9) { ++ let millions = count / 1e6; ++ return millions.toFixed(0).toString() + "M"; ++ } else { ++ let billions = count / 1e9; ++ return billions.toFixed(1).toString() + "B"; ++ } ++ }, ++ ++ setNotificationBadge: function(count) { ++ this._notificationBadgeCount = count; ++ let text = this._notificationBadgeCountToText(count); ++ this._notificationBadgeLabel.set_text(text); ++ }, ++ ++ toggleNotificationBadge: function(activate) { ++ if (activate && this._notificationBadgeCount > 0) { ++ this.updateNotificationBadge(); ++ this._notificationBadgeBin.show(); ++ } ++ else ++ this._notificationBadgeBin.hide(); ++ }, ++ ++ _showProgressOverlay: function() { ++ if (this._progressOverlayArea) { ++ this._updateProgressOverlay(); ++ return; ++ } ++ ++ this._progressOverlayArea = new St.DrawingArea({x_expand: true, y_expand: true}); ++ this._progressOverlayArea.add_style_class_name('progress-bar'); ++ this._progressOverlayArea.connect('repaint', () => { ++ this._drawProgressOverlay(this._progressOverlayArea); ++ }); ++ ++ this._source._iconContainer.add_child(this._progressOverlayArea); ++ let node = this._progressOverlayArea.get_theme_node(); ++ ++ let [hasColor, color] = node.lookup_color('-progress-bar-background', false); ++ if (hasColor) ++ this._progressbar_background = color ++ else ++ this._progressbar_background = new Clutter.Color({red: 204, green: 204, blue: 204, alpha: 255}); ++ ++ [hasColor, color] = node.lookup_color('-progress-bar-border', false); ++ if (hasColor) ++ this._progressbar_border = color; ++ else ++ this._progressbar_border = new Clutter.Color({red: 230, green: 230, blue: 230, alpha: 255}); ++ ++ this._updateProgressOverlay(); ++ }, ++ ++ _hideProgressOverlay: function() { ++ if (this._progressOverlayArea) ++ this._progressOverlayArea.destroy(); ++ ++ this._progressOverlayArea = null; ++ this._progressbar_background = null; ++ this._progressbar_border = null; ++ }, ++ ++ _updateProgressOverlay: function() { ++ ++ if (this._progressOverlayArea) { ++ this._progressOverlayArea.queue_repaint(); ++ } ++ }, ++ ++ _drawProgressOverlay: function(area) { ++ let scaleFactor = Utils.getScaleFactor(); ++ let [surfaceWidth, surfaceHeight] = area.get_surface_size(); ++ let cr = area.get_context(); ++ ++ let iconSize = this._source.icon.iconSize * scaleFactor; ++ ++ let x = Math.floor((surfaceWidth - iconSize) / 2); ++ let y = Math.floor((surfaceHeight - iconSize) / 2); ++ ++ let lineWidth = Math.floor(1.0 * scaleFactor); ++ let padding = Math.floor(iconSize * 0.05); ++ let width = iconSize - 2.0*padding; ++ let height = Math.floor(Math.min(18.0*scaleFactor, 0.20*iconSize)); ++ x += padding; ++ y += iconSize - height - padding; ++ ++ cr.setLineWidth(lineWidth); ++ ++ // Draw the outer stroke ++ let stroke = new Cairo.LinearGradient(0, y, 0, y + height); ++ let fill = null; ++ stroke.addColorStopRGBA(0.5, 0.5, 0.5, 0.5, 0.1); ++ stroke.addColorStopRGBA(0.9, 0.8, 0.8, 0.8, 0.4); ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill); ++ ++ // Draw the background ++ x += lineWidth; ++ y += lineWidth; ++ width -= 2.0*lineWidth; ++ height -= 2.0*lineWidth; ++ ++ stroke = Cairo.SolidPattern.createRGBA(0.20, 0.20, 0.20, 0.9); ++ fill = new Cairo.LinearGradient(0, y, 0, y + height); ++ fill.addColorStopRGBA(0.4, 0.25, 0.25, 0.25, 1.0); ++ fill.addColorStopRGBA(0.9, 0.35, 0.35, 0.35, 1.0); ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, width, height, true, true, stroke, fill); ++ ++ // Draw the finished bar ++ x += lineWidth; ++ y += lineWidth; ++ width -= 2.0*lineWidth; ++ height -= 2.0*lineWidth; ++ ++ let finishedWidth = Math.ceil(this._progress * width); ++ ++ let bg = this._progressbar_background; ++ let bd = this._progressbar_border; ++ ++ stroke = Cairo.SolidPattern.createRGBA(bd.red/255, bd.green/255, bd.blue/255, bd.alpha/255); ++ fill = Cairo.SolidPattern.createRGBA(bg.red/255, bg.green/255, bg.blue/255, bg.alpha/255); ++ ++ if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0 + width - finishedWidth, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill); ++ else ++ Utils.drawRoundedLine(cr, x + lineWidth/2.0, y + lineWidth/2.0, finishedWidth, height, true, true, stroke, fill); ++ ++ cr.$dispose(); ++ }, ++ ++ setProgress: function(progress) { ++ this._progress = Math.min(Math.max(progress, 0.0), 1.0); ++ this._updateProgressOverlay(); ++ }, ++ ++ toggleProgressOverlay: function(activate) { ++ if (activate) { ++ this._showProgressOverlay(); ++ } ++ else { ++ this._hideProgressOverlay(); ++ } ++ }, ++ ++ insertEntry: function(appProgress) { ++ if (!appProgress || this._progressManagerEntries.indexOf(appProgress) !== -1) ++ return; ++ ++ this._progressManagerEntries.push(appProgress); ++ this._selectEntry(appProgress); ++ }, ++ ++ removeEntry: function(appProgress) { ++ if (!appProgress || this._progressManagerEntries.indexOf(appProgress) == -1) ++ return; ++ ++ this._progressManagerEntries.splice(this._progressManagerEntries.indexOf(appProgress), 1); ++ ++ if (this._progressManagerEntries.length > 0) { ++ this._selectEntry(this._progressManagerEntries[this._progressManagerEntries.length-1]); ++ } else { ++ this.setNotificationBadge(0); ++ this.toggleNotificationBadge(false); ++ this.setProgress(0); ++ this.toggleProgressOverlay(false); ++ this.setUrgent(false); ++ } ++ }, ++ ++ _selectEntry: function(appProgress) { ++ if (!appProgress) ++ return; ++ ++ this._signalsHandler.removeWithLabel('progress-entry'); ++ ++ this._signalsHandler.addWithLabel('progress-entry', ++ [ ++ appProgress, ++ 'count-changed', ++ (appProgress, value) => { ++ this.setNotificationBadge(value); ++ } ++ ], [ ++ appProgress, ++ 'count-visible-changed', ++ (appProgress, value) => { ++ this.toggleNotificationBadge(value); ++ } ++ ], [ ++ appProgress, ++ 'progress-changed', ++ (appProgress, value) => { ++ this.setProgress(value); ++ } ++ ], [ ++ appProgress, ++ 'progress-visible-changed', ++ (appProgress, value) => { ++ this.toggleProgressOverlay(value); ++ } ++ ], [ ++ appProgress, ++ 'urgent-changed', ++ (appProgress, value) => { ++ this.setUrgent(value) ++ } ++ ]); ++ ++ this.setNotificationBadge(appProgress.count()); ++ this.toggleNotificationBadge(appProgress.countVisible()); ++ this.setProgress(appProgress.progress()); ++ this.toggleProgressOverlay(appProgress.progressVisible()); ++ ++ this._isUrgent = false; ++ }, ++ ++ setUrgent: function(urgent) { ++ const icon = this._source.icon._iconBin; ++ if (urgent) { ++ if (!this._isUrgent) { ++ icon.set_pivot_point(0.5, 0.5); ++ this._source.iconAnimator.addAnimation(icon, 'dance'); ++ this._isUrgent = true; ++ } ++ } else { ++ if (this._isUrgent) { ++ this._source.iconAnimator.removeAnimation(icon, 'dance'); ++ this._isUrgent = false; ++ } ++ icon.rotation_angle_z = 0; ++ } ++ } ++}); +diff --git a/extensions/dash-to-panel/proximity.js b/extensions/dash-to-panel/proximity.js +new file mode 100644 +index 00000000..c298f84c +--- /dev/null ++++ b/extensions/dash-to-panel/proximity.js +@@ -0,0 +1,262 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Lang = imports.lang; ++const Meta = imports.gi.Meta; ++ ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Utils = Me.imports.utils; ++ ++//timeout intervals ++const MIN_UPDATE_MS = 200; ++ ++//timeout names ++const T1 = 'limitUpdateTimeout'; ++ ++var Mode = { ++ ALL_WINDOWS: 0, ++ FOCUSED_WINDOWS: 1, ++ MAXIMIZED_WINDOWS: 2 ++}; ++ ++var ProximityWatch = Utils.defineClass({ ++ Name: 'DashToPanel.ProximityWatch', ++ ++ _init: function(actor, mode, xThreshold, yThreshold, handler) { ++ this.actor = actor; ++ this.overlap = 0; ++ this.mode = mode; ++ this.threshold = [xThreshold, yThreshold]; ++ this.handler = handler; ++ ++ this._allocationChangedId = actor.connect('notify::allocation', () => this._update()); ++ ++ this._update(); ++ }, ++ ++ destroy: function() { ++ this.actor.disconnect(this._allocationChangedId); ++ }, ++ ++ _update: function() { ++ this.monitorIndex = Main.layoutManager.findIndexForActor(this.actor); ++ ++ this._updateWatchRect(); ++ }, ++ ++ _updateWatchRect: function() { ++ let [actorX, actorY] = this.actor.get_position(); ++ ++ this.rect = new Meta.Rectangle({ ++ x: actorX - this.threshold[0], ++ y: actorY - this.threshold[1], ++ width: this.actor.width + this.threshold[0] * 2, ++ height: this.actor.height + this.threshold[1] * 2 ++ }); ++ }, ++}); ++ ++var ProximityManager = Utils.defineClass({ ++ Name: 'DashToPanel.ProximityManager', ++ ++ _init: function() { ++ this._counter = 1; ++ this._watches = {}; ++ this._focusedWindowInfo = null; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._timeoutsHandler = new Utils.TimeoutsHandler(); ++ ++ this._bindSignals(); ++ this._setFocusedWindow(); ++ }, ++ ++ createWatch: function(actor, mode, xThreshold, yThreshold, handler) { ++ let watch = new ProximityWatch(actor, mode, xThreshold, yThreshold, handler); ++ ++ this._watches[this._counter] = watch; ++ this.update(); ++ ++ return this._counter++; ++ }, ++ ++ removeWatch: function(id) { ++ if (this._watches[id]) { ++ this._watches[id].destroy(); ++ delete this._watches[id]; ++ } ++ }, ++ ++ update: function() { ++ this._queueUpdate(true); ++ }, ++ ++ destroy: function() { ++ this._signalsHandler.destroy(); ++ this._timeoutsHandler.destroy(); ++ this._disconnectFocusedWindow(); ++ Object.keys(this._watches).forEach(id => this.removeWatch(id)); ++ }, ++ ++ _bindSignals: function() { ++ this._signalsHandler.add( ++ [ ++ global.window_manager, ++ 'switch-workspace', ++ () => Object.keys(this._watches).forEach(id => this._watches[id].overlap = 0) ++ ], ++ [ ++ Main.overview, ++ 'hidden', ++ () => this._queueUpdate() ++ ], ++ [ ++ global.display, ++ 'notify::focus-window', ++ () => { ++ this._setFocusedWindow(); ++ this._queueUpdate(); ++ } ++ ], ++ [ ++ global.window_group, ++ [ ++ 'actor-added', ++ 'actor-removed' ++ ], ++ () => this._queueUpdate() ++ ] ++ ); ++ }, ++ ++ _setFocusedWindow: function() { ++ this._disconnectFocusedWindow(); ++ ++ let focusedWindow = global.display.focus_window; ++ ++ if (focusedWindow) { ++ let focusedWindowInfo = this._getFocusedWindowInfo(focusedWindow); ++ ++ if (focusedWindowInfo && this._checkIfHandledWindowType(focusedWindowInfo.metaWindow)) { ++ focusedWindowInfo.allocationId = focusedWindowInfo.window.connect('notify::allocation', () => this._queueUpdate()); ++ focusedWindowInfo.destroyId = focusedWindowInfo.window.connect('destroy', () => this._disconnectFocusedWindow(true)); ++ ++ this._focusedWindowInfo = focusedWindowInfo; ++ } ++ } ++ }, ++ ++ _getFocusedWindowInfo: function(focusedWindow) { ++ let window = focusedWindow.get_compositor_private(); ++ let focusedWindowInfo; ++ ++ if (window) { ++ focusedWindowInfo = { window: window }; ++ focusedWindowInfo.metaWindow = focusedWindowInfo.window.get_meta_window(); ++ ++ if (focusedWindow.is_attached_dialog()) { ++ let mainMetaWindow = focusedWindow.get_transient_for(); ++ ++ if (focusedWindowInfo.metaWindow.get_frame_rect().height < mainMetaWindow.get_frame_rect().height) { ++ focusedWindowInfo.window = mainMetaWindow.get_compositor_private(); ++ focusedWindowInfo.metaWindow = mainMetaWindow; ++ } ++ } ++ } ++ ++ return focusedWindowInfo; ++ }, ++ ++ _disconnectFocusedWindow: function(destroy) { ++ if (this._focusedWindowInfo && !destroy) { ++ this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.allocationId); ++ this._focusedWindowInfo.window.disconnect(this._focusedWindowInfo.destroyId); ++ } ++ ++ this._focusedWindowInfo = null; ++ }, ++ ++ _getHandledWindows: function() { ++ return global.get_window_actors() ++ .filter(w => w.visible) ++ .map(w => w.get_meta_window()) ++ .filter(mw => this._checkIfHandledWindow(mw)); ++ }, ++ ++ _checkIfHandledWindow: function(metaWindow) { ++ return metaWindow && !metaWindow.minimized && ++ this._checkIfHandledWindowType(metaWindow); ++ }, ++ ++ _checkIfHandledWindowType: function(metaWindow) { ++ let metaWindowType = metaWindow.get_window_type(); ++ ++ //https://www.roojs.org/seed/gir-1.2-gtk-3.0/seed/Meta.WindowType.html ++ return metaWindowType <= Meta.WindowType.SPLASHSCREEN && ++ metaWindowType != Meta.WindowType.DESKTOP; ++ }, ++ ++ _queueUpdate: function(noDelay) { ++ if (!noDelay && this._timeoutsHandler.getId(T1)) { ++ //limit the number of updates ++ this._pendingUpdate = true; ++ return; ++ } ++ ++ this._timeoutsHandler.add([T1, MIN_UPDATE_MS, () => this._endLimitUpdate()]); ++ ++ let metaWindows = this._getHandledWindows(); ++ ++ Object.keys(this._watches).forEach(id => { ++ let watch = this._watches[id]; ++ let overlap = this._update(watch, metaWindows); ++ ++ if (overlap !== watch.overlap) { ++ watch.handler(overlap); ++ watch.overlap = overlap; ++ } ++ }); ++ }, ++ ++ _endLimitUpdate: function() { ++ if (this._pendingUpdate) { ++ this._pendingUpdate = false; ++ this._queueUpdate(); ++ } ++ }, ++ ++ _update: function(watch, metaWindows) { ++ if (watch.mode === Mode.FOCUSED_WINDOWS) { ++ return (this._focusedWindowInfo && ++ this._checkIfHandledWindow(this._focusedWindowInfo.metaWindow) && ++ this._checkProximity(this._focusedWindowInfo.metaWindow, watch)); ++ } else if (watch.mode === Mode.MAXIMIZED_WINDOWS) { ++ return metaWindows.some(mw => mw.maximized_vertically && mw.maximized_horizontally && ++ mw.get_monitor() == watch.monitorIndex); ++ } ++ ++ //Mode.ALL_WINDOWS ++ return metaWindows.some(mw => this._checkProximity(mw, watch)); ++ }, ++ ++ _checkProximity: function(metaWindow, watch) { ++ return metaWindow.get_frame_rect().overlap(watch.rect); ++ }, ++}); +\ No newline at end of file +diff --git a/extensions/dash-to-panel/stylesheet.css b/extensions/dash-to-panel/stylesheet.css +new file mode 100644 +index 00000000..6917e24d +--- /dev/null ++++ b/extensions/dash-to-panel/stylesheet.css +@@ -0,0 +1,151 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++#dashtopanelTaskbar .dash-item-container > StWidget { ++ margin: 0; ++ padding: 0; ++} ++ ++#dashtopanelScrollview .app-well-app .overview-icon, ++.dashtopanelMainPanel .show-apps .overview-icon { ++ background: none; ++ border: none; ++ margin: 0; ++ padding: 0; ++} ++ ++#dashtopanelScrollview .app-well-app .overview-label { ++ /* must match TITLE_RIGHT_PADDING in apppicons.js */ ++ padding-right: 8px; ++} ++ ++#dashtopanelScrollview .app-well-app:hover .overview-icon, ++#dashtopanelScrollview .app-well-app:focus .overview-icon { ++ background: none; ++} ++ ++.dashtopanelMainPanel .show-apps:hover .overview-icon, ++#dashtopanelScrollview .app-well-app:hover .dtp-container, ++#dashtopanelScrollview .app-well-app:focus .dtp-container { ++ background-color: rgba(238, 238, 236, 0.1); ++} ++ ++#dashtopanelScrollview .app-well-app:hover .dtp-container.animate-appicon-hover { ++ background: none; ++} ++ ++#dashtopanelScrollview .app-well-app:active .dtp-container { ++ background-color: rgba(238, 238, 236, 0.18); ++} ++ ++#dashtopanelScrollview .app-well-app .favorite { ++ background-color: rgba(80, 150, 255, 0.4); ++} ++ ++#dashtopanelScrollview .app-well-app-running-dot { ++ margin-bottom: 0; ++} ++ ++#dashtopanelTaskbar .scrollview-fade { ++ background-gradient-end: rgba(0, 0, 0, 0); ++} ++ ++.dashtopanelSecondaryMenu { ++ max-width: 400px; ++} ++ ++.dashtopanelMainPanel.vertical .panel-button { ++ text-align: center; ++} ++ ++.dashtopanelMainPanel.vertical .panel-button.vertical *, ++.dashtopanelMainPanel.vertical .panel-button.clock-display * { ++ padding: 0; ++ margin: 0; ++} ++ ++.dashtopanelMainPanel.vertical .panel-button > *, ++.dashtopanelMainPanel.vertical .panel-button.vertical > *, ++.dashtopanelMainPanel.vertical .panel-button.clock-display > * { ++ padding: 8px 0; ++} ++ ++#dashtopanelThumbnailList { ++ spacing: 0em; ++ padding: 0 1em; ++} ++ ++#dashtopanelThumbnailList .popup-menu-item { ++ padding: 0; ++ border-radius: 5px; ++ spacing: 0; ++} ++ ++#dashtopanelThumbnailList .window-box { ++ padding: 0; ++ spacing: 0; ++} ++ ++#dashtopanelThumbnailList .preview-window-title { ++ padding-top: 1em; ++} ++ ++.popup-menu.panel-menu { ++ margin-bottom: 0; ++} ++ ++#panel #panelLeft, #panel #panelCenter { ++ spacing: 0px; ++} ++ ++.showdesktop-button-dark-hovered { ++ background-color: rgba(200, 200, 200, .4); ++} ++ ++.showdesktop-button-light-hovered { ++ background-color: rgba(55, 55, 55, .4); ++} ++ ++.panel-corner.hidden:active, .panel-corner.hidden:overview, .panel-corner.hidden:focus { ++ -panel-corner-border-color: rgba(0, 0, 0, .001); ++} ++#dashtopanelScrollview .badge { ++ color: rgba(255, 255, 255, 1); ++ font-weight: bold; ++ text-align: center; ++} ++ ++#dashtopanelScrollview .number-overlay { ++ background-color: rgba(0,0,0,0.8); ++} ++ ++#dashtopanelScrollview .notification-badge { ++ background-color: rgba(255,0,0,0.8); ++} ++ ++#dashtopanelScrollview .progress-bar { ++ /* Customization of the progress bar style, e.g.: ++ -progress-bar-background: rgba(0.8, 0.8, 0.8, 1); ++ -progress-bar-border: rgba(0.9, 0.9, 0.9, 1); ++ */ ++} +diff --git a/extensions/dash-to-panel/taskbar.js b/extensions/dash-to-panel/taskbar.js +new file mode 100644 +index 00000000..5feb1a99 +--- /dev/null ++++ b/extensions/dash-to-panel/taskbar.js +@@ -0,0 +1,1602 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++ ++const Clutter = imports.gi.Clutter; ++const Config = imports.misc.config; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const GObject = imports.gi.GObject; ++const Gtk = imports.gi.Gtk; ++const Signals = imports.signals; ++const Lang = imports.lang; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++ ++const AppDisplay = imports.ui.appDisplay; ++const AppFavorites = imports.ui.appFavorites; ++const Dash = imports.ui.dash; ++const DND = imports.ui.dnd; ++const IconGrid = imports.ui.iconGrid; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const AppIcons = Me.imports.appIcons; ++const Panel = Me.imports.panel; ++const PanelManager = Me.imports.panelManager; ++const PanelSettings = Me.imports.panelSettings; ++const Pos = Me.imports.panelPositions; ++const Utils = Me.imports.utils; ++const WindowPreview = Me.imports.windowPreview; ++ ++var DASH_ANIMATION_TIME = Dash.DASH_ANIMATION_TIME / (Dash.DASH_ANIMATION_TIME > 1 ? 1000 : 1); ++var DASH_ITEM_HOVER_TIMEOUT = Dash.DASH_ITEM_HOVER_TIMEOUT; ++var MIN_ICON_SIZE = 4; ++ ++/** ++ * Extend DashItemContainer ++ * ++ * - set label position based on taskbar orientation ++ * ++ * I can't subclass the original object because of this: https://bugzilla.gnome.org/show_bug.cgi?id=688973. ++ * thus use this ugly pattern. ++ */ ++ ++function extendDashItemContainer(dashItemContainer) { ++ dashItemContainer.showLabel = AppIcons.ItemShowLabel; ++}; ++ ++const iconAnimationSettings = { ++ _getDictValue: function(key) { ++ let type = Me.settings.get_string('animate-appicon-hover-animation-type'); ++ return Me.settings.get_value(key).deep_unpack()[type] || 0; ++ }, ++ ++ get type() { ++ if (!Me.settings.get_boolean('animate-appicon-hover')) ++ return ""; ++ ++ return Me.settings.get_string('animate-appicon-hover-animation-type'); ++ }, ++ ++ get convexity() { ++ return Math.max(0, this._getDictValue('animate-appicon-hover-animation-convexity')); ++ }, ++ ++ get duration() { ++ return this._getDictValue('animate-appicon-hover-animation-duration'); ++ }, ++ ++ get extent() { ++ return Math.max(1, this._getDictValue('animate-appicon-hover-animation-extent')); ++ }, ++ ++ get rotation() { ++ return this._getDictValue('animate-appicon-hover-animation-rotation'); ++ }, ++ ++ get travel() { ++ return Math.max(0, this._getDictValue('animate-appicon-hover-animation-travel')); ++ }, ++ ++ get zoom() { ++ return Math.max(1, this._getDictValue('animate-appicon-hover-animation-zoom')); ++ }, ++}; ++ ++/* This class is a fork of the upstream DashActor class (ui.dash.js) ++ * ++ * Summary of changes: ++ * - modified chldBox calculations for when 'show-apps-at-top' option is checked ++ * - handle horizontal dash ++ */ ++var taskbarActor = Utils.defineClass({ ++ Name: 'DashToPanel-TaskbarActor', ++ Extends: St.Widget, ++ ++ _init: function(delegate) { ++ this._delegate = delegate; ++ this._currentBackgroundColor = 0; ++ this.callParent('_init', { name: 'dashtopanelTaskbar', ++ layout_manager: new Clutter.BoxLayout({ orientation: Clutter.Orientation[delegate.dtpPanel.getOrientation().toUpperCase()] }), ++ clip_to_allocation: true }); ++ }, ++ ++ vfunc_allocate: function(box, flags)  { ++ Utils.setAllocation(this, box, flags); ++ ++ let panel = this._delegate.dtpPanel; ++ let availFixedSize = box[panel.fixedCoord.c2] - box[panel.fixedCoord.c1]; ++ let availVarSize = box[panel.varCoord.c2] - box[panel.varCoord.c1]; ++ let [dummy, scrollview, leftFade, rightFade] = this.get_children(); ++ let [, natSize] = this[panel.sizeFunc](availFixedSize); ++ let childBox = new Clutter.ActorBox(); ++ let orientation = panel.getOrientation(); ++ ++ Utils.allocate(dummy, childBox, flags); ++ ++ childBox[panel.varCoord.c1] = box[panel.varCoord.c1]; ++ childBox[panel.varCoord.c2] = Math.min(availVarSize, natSize); ++ childBox[panel.fixedCoord.c1] = box[panel.fixedCoord.c1]; ++ childBox[panel.fixedCoord.c2] = box[panel.fixedCoord.c2]; ++ ++ Utils.allocate(scrollview, childBox, flags); ++ ++ let [value, , upper, , , pageSize] = scrollview[orientation[0] + 'scroll'].adjustment.get_values(); ++ upper = Math.floor(upper); ++ scrollview._dtpFadeSize = upper > pageSize ? this._delegate.iconSize : 0; ++ ++ if (this._currentBackgroundColor !== panel.dynamicTransparency.currentBackgroundColor) { ++ this._currentBackgroundColor = panel.dynamicTransparency.currentBackgroundColor; ++ let gradientStyle = 'background-gradient-start: ' + this._currentBackgroundColor + ++ 'background-gradient-direction: ' + orientation; ++ ++ leftFade.set_style(gradientStyle); ++ rightFade.set_style(gradientStyle); ++ } ++ ++ childBox[panel.varCoord.c2] = childBox[panel.varCoord.c1] + (value > 0 ? scrollview._dtpFadeSize : 0); ++ Utils.allocate(leftFade, childBox, flags); ++ ++ childBox[panel.varCoord.c1] = box[panel.varCoord.c2] - (value + pageSize < upper ? scrollview._dtpFadeSize : 0); ++ childBox[panel.varCoord.c2] = box[panel.varCoord.c2]; ++ Utils.allocate(rightFade, childBox, flags); ++ }, ++ ++ // We want to request the natural size of all our children ++ // as our natural width, so we chain up to StWidget (which ++ // then calls BoxLayout) ++ vfunc_get_preferred_width: function(forHeight) { ++ let [, natWidth] = St.Widget.prototype.vfunc_get_preferred_width.call(this, forHeight); ++ ++ return [0, natWidth]; ++ }, ++ ++ vfunc_get_preferred_height: function(forWidth) { ++ let [, natHeight] = St.Widget.prototype.vfunc_get_preferred_height.call(this, forWidth); ++ ++ return [0, natHeight]; ++ }, ++}); ++ ++/* This class is a fork of the upstream dash class (ui.dash.js) ++ * ++ * Summary of changes: ++ * - disconnect global signals adding a destroy method; ++ * - play animations even when not in overview mode ++ * - set a maximum icon size ++ * - show running and/or favorite applications ++ * - emit a custom signal when an app icon is added ++ * - Add scrollview ++ * Ensure actor is visible on keyfocus inside the scrollview ++ * - add 128px icon size, might be useful for hidpi display ++ * - Sync minimization application target position. ++ */ ++ ++var taskbar = Utils.defineClass({ ++ Name: 'DashToPanel.Taskbar', ++ ++ _init : function(panel) { ++ this.dtpPanel = panel; ++ ++ // start at smallest size due to running indicator drawing area expanding but not shrinking ++ this.iconSize = 16; ++ ++ this._shownInitially = false; ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ this._showLabelTimeoutId = 0; ++ this._resetHoverTimeoutId = 0; ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ this._labelShowing = false; ++ this.fullScrollView = 0; ++ ++ let isVertical = panel.checkIfVertical(); ++ ++ this._box = new St.BoxLayout({ vertical: isVertical, ++ clip_to_allocation: false, ++ x_align: Clutter.ActorAlign.START, ++ y_align: Clutter.ActorAlign.START }); ++ ++ this._container = new taskbarActor(this); ++ this._scrollView = new St.ScrollView({ name: 'dashtopanelScrollview', ++ hscrollbar_policy: Gtk.PolicyType.NEVER, ++ vscrollbar_policy: Gtk.PolicyType.NEVER, ++ enable_mouse_scrolling: true }); ++ ++ this._scrollView.connect('leave-event', Lang.bind(this, this._onLeaveEvent)); ++ this._scrollView.connect('motion-event', Lang.bind(this, this._onMotionEvent)); ++ this._scrollView.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); ++ this._scrollView.add_actor(this._box); ++ ++ this._showAppsIconWrapper = panel.showAppsIconWrapper; ++ this._showAppsIconWrapper.connect('menu-state-changed', Lang.bind(this, function(showAppsIconWrapper, opened) { ++ this._itemMenuStateChanged(showAppsIconWrapper, opened); ++ })); ++ // an instance of the showAppsIcon class is encapsulated in the wrapper ++ this._showAppsIcon = this._showAppsIconWrapper.realShowAppsIcon; ++ this.showAppsButton = this._showAppsIcon.toggleButton; ++ ++ if (isVertical) { ++ this.showAppsButton.set_width(panel.geom.w); ++ } ++ ++ this.showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled)); ++ this.showAppsButton.checked = Main.overview.viewSelector._showAppsButton.checked; ++ ++ this._showAppsIcon.childScale = 1; ++ this._showAppsIcon.childOpacity = 255; ++ this._showAppsIcon.icon.setIconSize(this.iconSize); ++ this._hookUpLabel(this._showAppsIcon, this._showAppsIconWrapper); ++ ++ this._container.add_child(new St.Widget({ width: 0, reactive: false })); ++ this._container.add_actor(this._scrollView); ++ ++ let orientation = panel.getOrientation(); ++ let fadeStyle = 'background-gradient-direction:' + orientation; ++ let fade1 = new St.Widget({ style_class: 'scrollview-fade', reactive: false }); ++ let fade2 = new St.Widget({ style_class: 'scrollview-fade', ++ reactive: false, ++ pivot_point: Utils.getPoint({ x: .5, y: .5 }), ++ rotation_angle_z: 180 }); ++ ++ fade1.set_style(fadeStyle); ++ fade2.set_style(fadeStyle); ++ ++ this._container.add_actor(fade1); ++ this._container.add_actor(fade2); ++ ++ this.previewMenu = new WindowPreview.PreviewMenu(panel); ++ this.previewMenu.enable(); ++ ++ let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; ++ this.actor = new St.Bin({ child: this._container, ++ y_align: St.Align.START, x_align:rtl?St.Align.END:St.Align.START ++ }); ++ ++ let adjustment = this._scrollView[orientation[0] + 'scroll'].adjustment; ++ ++ this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay)); ++ ++ this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' }); ++ ++ this._appSystem = Shell.AppSystem.get_default(); ++ ++ this.iconAnimator = new PanelManager.IconAnimator(this.dtpPanel.panel.actor); ++ ++ this._signalsHandler.add( ++ [ ++ this.dtpPanel.panel.actor, ++ 'notify::height', ++ () => this._queueRedisplay() ++ ], ++ [ ++ this.dtpPanel.panel.actor, ++ 'notify::width', ++ () => this._queueRedisplay() ++ ], ++ [ ++ this._appSystem, ++ 'installed-changed', ++ Lang.bind(this, function() { ++ AppFavorites.getAppFavorites().reload(); ++ this._queueRedisplay(); ++ }) ++ ], ++ [ ++ this._appSystem, ++ 'app-state-changed', ++ Lang.bind(this, this._queueRedisplay) ++ ], ++ [ ++ AppFavorites.getAppFavorites(), ++ 'changed', ++ Lang.bind(this, this._queueRedisplay) ++ ], ++ [ ++ global.window_manager, ++ 'switch-workspace', ++ () => this._connectWorkspaceSignals() ++ ], ++ [ ++ Utils.DisplayWrapper.getScreen(), ++ [ ++ 'window-entered-monitor', ++ 'window-left-monitor' ++ ], ++ () => { ++ if (Me.settings.get_boolean('isolate-monitors')) { ++ this._queueRedisplay(); ++ } ++ } ++ ], ++ [ ++ Main.overview, ++ 'item-drag-begin', ++ Lang.bind(this, this._onDragBegin) ++ ], ++ [ ++ Main.overview, ++ 'item-drag-end', ++ Lang.bind(this, this._onDragEnd) ++ ], ++ [ ++ Main.overview, ++ 'item-drag-cancelled', ++ Lang.bind(this, this._onDragCancelled) ++ ], ++ [ ++ // Ensure the ShowAppsButton status is kept in sync ++ Main.overview.viewSelector._showAppsButton, ++ 'notify::checked', ++ Lang.bind(this, this._syncShowAppsButtonToggled) ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::dot-size', ++ 'changed::show-favorites', ++ 'changed::show-running-apps', ++ 'changed::show-favorites-all-monitors' ++ ], ++ Lang.bind(this, this._redisplay) ++ ], ++ [ ++ Me.settings, ++ 'changed::group-apps', ++ Lang.bind(this, function() { ++ this.isGroupApps = Me.settings.get_boolean('group-apps'); ++ this._connectWorkspaceSignals(); ++ }) ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::group-apps-use-launchers', ++ 'changed::taskbar-locked' ++ ], ++ () => this.resetAppIcons() ++ ], ++ [ ++ adjustment, ++ [ ++ 'notify::upper', ++ 'notify::pageSize' ++ ], ++ () => this._onScrollSizeChange(adjustment) ++ ] ++ ); ++ ++ this.isGroupApps = Me.settings.get_boolean('group-apps'); ++ ++ this._onScrollSizeChange(adjustment); ++ this._connectWorkspaceSignals(); ++ }, ++ ++ destroy: function() { ++ this.iconAnimator.destroy(); ++ ++ this._signalsHandler.destroy(); ++ this._signalsHandler = 0; ++ ++ this._container.destroy(); ++ ++ this.previewMenu.disable(); ++ this.previewMenu.destroy(); ++ ++ this._disconnectWorkspaceSignals(); ++ }, ++ ++ _dropIconAnimations: function() { ++ this._getTaskbarIcons().forEach(item => { ++ item.raise(0); ++ item.stretch(0); ++ }); ++ }, ++ ++ _updateIconAnimations: function(pointerX, pointerY) { ++ this._iconAnimationTimestamp = Date.now(); ++ let type = iconAnimationSettings.type; ++ ++ if (!pointerX || !pointerY) ++ [pointerX, pointerY] = global.get_pointer(); ++ ++ this._getTaskbarIcons().forEach(item => { ++ let [x, y] = item.get_transformed_position(); ++ let [width, height] = item.get_transformed_size(); ++ let [centerX, centerY] = [x + width / 2, y + height / 2]; ++ let size = this._box.vertical ? height : width; ++ let difference = this._box.vertical ? pointerY - centerY : pointerX - centerX; ++ let distance = Math.abs(difference); ++ let maxDistance = (iconAnimationSettings.extent / 2) * size; ++ ++ if (type == 'PLANK') { ++ // Make the position stable for items that are far from the pointer. ++ let translation = distance <= maxDistance ? ++ distance / (2 + 8 * distance / maxDistance) : ++ // the previous expression with distance = maxDistance ++ maxDistance / 10; ++ ++ if (difference > 0) ++ translation *= -1; ++ ++ item.stretch(translation); ++ } ++ ++ if (distance <= maxDistance) { ++ let level = (maxDistance - distance) / maxDistance; ++ level = Math.pow(level, iconAnimationSettings.convexity); ++ item.raise(level); ++ } else { ++ item.raise(0); ++ } ++ }); ++ }, ++ ++ _onLeaveEvent: function(actor) { ++ let [stageX, stageY] = global.get_pointer(); ++ let [success, x, y] = actor.transform_stage_point(stageX, stageY); ++ if (success && !actor.allocation.contains(x, y) && (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK')) ++ this._dropIconAnimations(); ++ ++ return Clutter.EVENT_PROPAGATE; ++ }, ++ ++ _onMotionEvent: function(actor_, event) { ++ if (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK') { ++ let timestamp = Date.now(); ++ if (!this._iconAnimationTimestamp || ++ (timestamp - this._iconAnimationTimestamp >= iconAnimationSettings.duration / 2)) { ++ let [pointerX, pointerY] = event.get_coords(); ++ this._updateIconAnimations(pointerX, pointerY); ++ } ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ }, ++ ++ _onScrollEvent: function(actor, event) { ++ ++ let orientation = this.dtpPanel.getOrientation(); ++ ++ // reset timeout to avid conflicts with the mousehover event ++ if (this._ensureAppIconVisibilityTimeoutId>0) { ++ Mainloop.source_remove(this._ensureAppIconVisibilityTimeoutId); ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ } ++ ++ // Skip to avoid double events mouse ++ if (event.is_pointer_emulated()) ++ return Clutter.EVENT_STOP; ++ ++ let adjustment, delta; ++ ++ adjustment = this._scrollView[orientation[0] + 'scroll'].get_adjustment(); ++ ++ let increment = adjustment.step_increment; ++ ++ switch ( event.get_scroll_direction() ) { ++ case Clutter.ScrollDirection.UP: ++ case Clutter.ScrollDirection.LEFT: ++ delta = -increment; ++ break; ++ case Clutter.ScrollDirection.DOWN: ++ case Clutter.ScrollDirection.RIGHT: ++ delta = +increment; ++ break; ++ case Clutter.ScrollDirection.SMOOTH: ++ let [dx, dy] = event.get_scroll_delta(); ++ delta = dy*increment; ++ delta += dx*increment; ++ break; ++ ++ } ++ ++ adjustment.set_value(adjustment.get_value() + delta); ++ ++ return Clutter.EVENT_STOP; ++ ++ }, ++ ++ _onScrollSizeChange: function(adjustment) { ++ // Update minimization animation target position on scrollview change. ++ this._updateAppIcons(); ++ ++ // When applications are ungrouped and there is some empty space on the horizontal taskbar, ++ // force a fixed label width to prevent the icons from "wiggling" when an animation runs ++ // (adding or removing an icon). When the taskbar is full, revert to a dynamic label width ++ // to allow them to resize and make room for new icons. ++ if (!this.dtpPanel.checkIfVertical() && !this.isGroupApps) { ++ let initial = this.fullScrollView; ++ ++ if (!this.fullScrollView && Math.floor(adjustment.upper) > adjustment.page_size) { ++ this.fullScrollView = adjustment.page_size; ++ } else if (adjustment.page_size < this.fullScrollView) { ++ this.fullScrollView = 0; ++ } ++ ++ if (initial != this.fullScrollView) { ++ this._getAppIcons().forEach(a => a.updateTitleStyle()); ++ } ++ } ++ }, ++ ++ _onDragBegin: function() { ++ this._dragCancelled = false; ++ this._dragMonitor = { ++ dragMotion: Lang.bind(this, this._onDragMotion) ++ }; ++ DND.addDragMonitor(this._dragMonitor); ++ ++ if (this._box.get_n_children() == 0) { ++ this._emptyDropTarget = new Dash.EmptyDropTargetItem(); ++ this._box.insert_child_at_index(this._emptyDropTarget, 0); ++ this._emptyDropTarget.show(true); ++ } ++ ++ this._toggleFavortieHighlight(true); ++ }, ++ ++ _onDragCancelled: function() { ++ this._dragCancelled = true; ++ ++ if (this._dragInfo) { ++ this._box.set_child_at_index(this._dragInfo[1]._dashItemContainer, this._dragInfo[0]); ++ } ++ ++ this._endDrag(); ++ }, ++ ++ _onDragEnd: function() { ++ if (this._dragCancelled) ++ return; ++ ++ this._endDrag(); ++ }, ++ ++ _endDrag: function() { ++ if (this._dragInfo && this._dragInfo[1]._dashItemContainer instanceof DragPlaceholderItem) { ++ this._box.remove_child(this._dragInfo[1]._dashItemContainer); ++ this._dragInfo[1]._dashItemContainer.destroy(); ++ delete this._dragInfo[1]._dashItemContainer; ++ } ++ ++ this._dragInfo = null; ++ this._clearEmptyDropTarget(); ++ this._showAppsIcon.setDragApp(null); ++ DND.removeDragMonitor(this._dragMonitor); ++ ++ this._toggleFavortieHighlight(); ++ }, ++ ++ _onDragMotion: function(dragEvent) { ++ let app = Dash.getAppFromSource(dragEvent.source); ++ if (app == null) ++ return DND.DragMotionResult.CONTINUE; ++ ++ let showAppsHovered = this._showAppsIcon.contains(dragEvent.targetActor); ++ ++ if (showAppsHovered) ++ this._showAppsIcon.setDragApp(app); ++ else ++ this._showAppsIcon.setDragApp(null); ++ ++ return DND.DragMotionResult.CONTINUE; ++ }, ++ ++ _toggleFavortieHighlight: function(show) { ++ let appFavorites = AppFavorites.getAppFavorites(); ++ let cssFuncName = (show ? 'add' : 'remove') + '_style_class_name'; ++ ++ this._getAppIcons().filter(appIcon => appFavorites.isFavorite(appIcon.app.get_id())) ++ .forEach(fav => fav._container[cssFuncName]('favorite')); ++ }, ++ ++ handleIsolatedWorkspaceSwitch: function() { ++ this._shownInitially = this.isGroupApps; ++ this._queueRedisplay(); ++ }, ++ ++ _connectWorkspaceSignals: function() { ++ this._disconnectWorkspaceSignals(); ++ ++ this._lastWorkspace = Utils.DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++ ++ this._workspaceWindowAddedId = this._lastWorkspace.connect('window-added', () => this._queueRedisplay()); ++ this._workspaceWindowRemovedId = this._lastWorkspace.connect('window-removed', () => this._queueRedisplay()); ++ }, ++ ++ _disconnectWorkspaceSignals: function() { ++ if (this._lastWorkspace) { ++ this._lastWorkspace.disconnect(this._workspaceWindowAddedId); ++ this._lastWorkspace.disconnect(this._workspaceWindowRemovedId); ++ ++ this._lastWorkspace = null; ++ } ++ }, ++ ++ _queueRedisplay: function () { ++ Main.queueDeferredWork(this._workId); ++ }, ++ ++ _hookUpLabel: function(item, syncHandler) { ++ item.child.connect('notify::hover', Lang.bind(this, function() { ++ this._syncLabel(item, syncHandler); ++ })); ++ ++ syncHandler.connect('sync-tooltip', Lang.bind(this, function() { ++ this._syncLabel(item, syncHandler); ++ })); ++ }, ++ ++ _createAppItem: function(app, window, isLauncher) { ++ let appIcon = new AppIcons.taskbarAppIcon( ++ { ++ app: app, ++ window: window, ++ isLauncher: isLauncher ++ }, ++ this.dtpPanel, ++ { ++ setSizeManually: true, ++ showLabel: false, ++ isDraggable: !Me.settings.get_boolean('taskbar-locked'), ++ }, ++ this.previewMenu, ++ this.iconAnimator ++ ); ++ ++ if (appIcon._draggable) { ++ appIcon._draggable.connect('drag-begin', ++ Lang.bind(this, function() { ++ appIcon.actor.opacity = 0; ++ appIcon.isDragged = 1; ++ this._dropIconAnimations(); ++ })); ++ appIcon._draggable.connect('drag-end', ++ Lang.bind(this, function() { ++ appIcon.actor.opacity = 255; ++ delete appIcon.isDragged; ++ this._updateAppIcons(); ++ })); ++ } ++ ++ appIcon.connect('menu-state-changed', ++ Lang.bind(this, function(appIcon, opened) { ++ this._itemMenuStateChanged(item, opened); ++ })); ++ ++ let item = new TaskbarItemContainer(); ++ ++ item._dtpPanel = this.dtpPanel ++ extendDashItemContainer(item); ++ ++ item.setChild(appIcon.actor); ++ appIcon._dashItemContainer = item; ++ ++ appIcon.actor.connect('notify::hover', Lang.bind(this, function() { ++ if (appIcon.actor.hover){ ++ this._ensureAppIconVisibilityTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function(){ ++ Utils.ensureActorVisibleInScrollView(this._scrollView, appIcon.actor, this._scrollView._dtpFadeSize); ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ ++ if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE') ++ appIcon.actor.get_parent().raise(1); ++ else if (!appIcon.isDragged && (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK')) ++ this._updateIconAnimations(); ++ } else { ++ if (this._ensureAppIconVisibilityTimeoutId>0) { ++ Mainloop.source_remove(this._ensureAppIconVisibilityTimeoutId); ++ this._ensureAppIconVisibilityTimeoutId = 0; ++ } ++ ++ if (!appIcon.isDragged && iconAnimationSettings.type == 'SIMPLE') ++ appIcon.actor.get_parent().raise(0); ++ } ++ })); ++ ++ appIcon.actor.connect('clicked', ++ Lang.bind(this, function(actor) { ++ Utils.ensureActorVisibleInScrollView(this._scrollView, actor, this._scrollView._dtpFadeSize); ++ })); ++ ++ appIcon.actor.connect('key-focus-in', Lang.bind(this, function(actor) { ++ let [x_shift, y_shift] = Utils.ensureActorVisibleInScrollView(this._scrollView, actor, this._scrollView._dtpFadeSize); ++ ++ // This signal is triggered also by mouse click. The popup menu is opened at the original ++ // coordinates. Thus correct for the shift which is going to be applied to the scrollview. ++ if (appIcon._menu) { ++ appIcon._menu._boxPointer.xOffset = -x_shift; ++ appIcon._menu._boxPointer.yOffset = -y_shift; ++ } ++ })); ++ ++ // Override default AppIcon label_actor, now the ++ // accessible_name is set at DashItemContainer.setLabelText ++ appIcon.actor.label_actor = null; ++ item.setLabelText(app.get_name()); ++ ++ appIcon.icon.setIconSize(this.iconSize); ++ this._hookUpLabel(item, appIcon); ++ ++ return item; ++ }, ++ ++ // Return an array with the "proper" appIcons currently in the taskbar ++ _getAppIcons: function() { ++ // Only consider children which are "proper" icons and which are not ++ // animating out (which means they will be destroyed at the end of ++ // the animation) ++ return this._getTaskbarIcons().map(function(actor){ ++ return actor.child._delegate; ++ }); ++ }, ++ ++ _getTaskbarIcons: function(includeAnimated) { ++ return this._box.get_children().filter(function(actor) { ++ return actor.child && ++ actor.child._delegate && ++ actor.child._delegate.icon && ++ (includeAnimated || !actor.animatingOut); ++ }); ++ }, ++ ++ _updateAppIcons: function() { ++ let appIcons = this._getAppIcons(); ++ ++ appIcons.filter(icon => icon.constructor === AppIcons.taskbarAppIcon).forEach(icon => { ++ icon.updateIcon(); ++ }); ++ }, ++ ++ _itemMenuStateChanged: function(item, opened) { ++ // When the menu closes, it calls sync_hover, which means ++ // that the notify::hover handler does everything we need to. ++ if (opened) { ++ if (this._showLabelTimeoutId > 0) { ++ Mainloop.source_remove(this._showLabelTimeoutId); ++ this._showLabelTimeoutId = 0; ++ } ++ ++ item.hideLabel(); ++ } else { ++ // I want to listen from outside when a menu is closed. I used to ++ // add a custom signal to the appIcon, since gnome 3.8 the signal ++ // calling this callback was added upstream. ++ this.emit('menu-closed'); ++ ++ // The icon menu grabs the events and, once it is closed, the pointer is maybe ++ // no longer over the taskbar and the animations are not dropped. ++ if (iconAnimationSettings.type == 'RIPPLE' || iconAnimationSettings.type == 'PLANK') { ++ this._scrollView.sync_hover(); ++ if (!this._scrollView.hover) ++ this._dropIconAnimations(); ++ } ++ } ++ }, ++ ++ _syncLabel: function (item, syncHandler) { ++ let shouldShow = syncHandler ? syncHandler.shouldShowTooltip() : item.child.get_hover(); ++ ++ if (shouldShow) { ++ if (this._showLabelTimeoutId == 0) { ++ let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT; ++ this._showLabelTimeoutId = Mainloop.timeout_add(timeout, ++ Lang.bind(this, function() { ++ this._labelShowing = true; ++ item.showLabel(); ++ this._showLabelTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel'); ++ if (this._resetHoverTimeoutId > 0) { ++ Mainloop.source_remove(this._resetHoverTimeoutId); ++ this._resetHoverTimeoutId = 0; ++ } ++ } ++ } else { ++ if (this._showLabelTimeoutId > 0) ++ Mainloop.source_remove(this._showLabelTimeoutId); ++ this._showLabelTimeoutId = 0; ++ item.hideLabel(); ++ if (this._labelShowing) { ++ this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT, ++ Lang.bind(this, function() { ++ this._labelShowing = false; ++ this._resetHoverTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ })); ++ GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing'); ++ } ++ } ++ }, ++ ++ _adjustIconSize: function() { ++ const thisMonitorIndex = this.dtpPanel.monitor.index; ++ let panelSize = PanelSettings.getPanelSize(Me.settings, thisMonitorIndex); ++ let availSize = panelSize - Me.settings.get_int('appicon-padding') * 2; ++ let minIconSize = MIN_ICON_SIZE + panelSize % 2; ++ ++ if (availSize == this.iconSize) ++ return; ++ ++ if (availSize < minIconSize) { ++ availSize = minIconSize; ++ } ++ ++ // For the icon size, we only consider children which are "proper" ++ // icons and which are not animating out (which means they will be ++ // destroyed at the end of the animation) ++ let iconChildren = this._getTaskbarIcons().concat([this._showAppsIcon]); ++ let scale = this.iconSize / availSize; ++ ++ this.iconSize = availSize; ++ ++ for (let i = 0; i < iconChildren.length; i++) { ++ let icon = iconChildren[i].child._delegate.icon; ++ ++ // Set the new size immediately, to keep the icons' sizes ++ // in sync with this.iconSize ++ icon.setIconSize(this.iconSize); ++ ++ // Don't animate the icon size change when the overview ++ // is transitioning, or when initially filling ++ // the taskbar ++ if (Main.overview.animationInProgress || ++ !this._shownInitially) ++ continue; ++ ++ let [targetWidth, targetHeight] = icon.icon.get_size(); ++ ++ // Scale the icon's texture to the previous size and ++ // tween to the new size ++ icon.icon.set_size(icon.icon.width * scale, icon.icon.height * scale); ++ ++ Utils.animate(icon.icon, ++ { width: targetWidth, ++ height: targetHeight, ++ time: DASH_ANIMATION_TIME, ++ transition: 'easeOutQuad', ++ }); ++ } ++ }, ++ ++ sortAppsCompareFunction: function(appA, appB) { ++ return getAppStableSequence(appA, this.dtpPanel.monitor) - ++ getAppStableSequence(appB, this.dtpPanel.monitor); ++ }, ++ ++ getAppInfos: function() { ++ //get the user's favorite apps ++ let favoriteApps = this._checkIfShowingFavorites() ? AppFavorites.getAppFavorites().getFavorites() : []; ++ ++ //find the apps that should be in the taskbar: the favorites first, then add the running apps ++ // When using isolation, we filter out apps that have no windows in ++ // the current workspace (this check is done in AppIcons.getInterestingWindows) ++ let runningApps = this._checkIfShowingRunningApps() ? this._getRunningApps().sort(this.sortAppsCompareFunction.bind(this)) : []; ++ ++ if (!this.isGroupApps && Me.settings.get_boolean('group-apps-use-launchers')) { ++ return this._createAppInfos(favoriteApps, [], true) ++ .concat(this._createAppInfos(runningApps) ++ .filter(appInfo => appInfo.windows.length)); ++ } else { ++ return this._createAppInfos(favoriteApps.concat(runningApps.filter(app => favoriteApps.indexOf(app) < 0))) ++ .filter(appInfo => appInfo.windows.length || favoriteApps.indexOf(appInfo.app) >= 0); ++ } ++ }, ++ ++ _redisplay: function () { ++ if (!this._signalsHandler) { ++ return; ++ } ++ ++ //get the currently displayed appIcons ++ let currentAppIcons = this._getTaskbarIcons(); ++ let expectedAppInfos = this.getAppInfos(); ++ ++ //remove the appIcons which are not in the expected apps list ++ for (let i = currentAppIcons.length - 1; i > -1; --i) { ++ let appIcon = currentAppIcons[i].child._delegate; ++ let appIndex = Utils.findIndex(expectedAppInfos, appInfo => appInfo.app == appIcon.app && ++ appInfo.isLauncher == appIcon.isLauncher); ++ ++ if (appIndex < 0 || ++ (appIcon.window && (this.isGroupApps || expectedAppInfos[appIndex].windows.indexOf(appIcon.window) < 0)) || ++ (!appIcon.window && !appIcon.isLauncher && ++ !this.isGroupApps && expectedAppInfos[appIndex].windows.length)) { ++ currentAppIcons[i][this._shownInitially ? 'animateOutAndDestroy' : 'destroy'](); ++ currentAppIcons.splice(i, 1); ++ } ++ } ++ ++ //if needed, reorder the existing appIcons and create the missing ones ++ let currentPosition = 0; ++ for (let i = 0, l = expectedAppInfos.length; i < l; ++i) { ++ let neededAppIcons = this.isGroupApps || !expectedAppInfos[i].windows.length ? ++ [{ app: expectedAppInfos[i].app, window: null, isLauncher: expectedAppInfos[i].isLauncher }] : ++ expectedAppInfos[i].windows.map(window => ({ app: expectedAppInfos[i].app, window: window, isLauncher: false })); ++ ++ for (let j = 0, ll = neededAppIcons.length; j < ll; ++j) { ++ //check if the icon already exists ++ let matchingAppIconIndex = Utils.findIndex(currentAppIcons, appIcon => appIcon.child._delegate.app == neededAppIcons[j].app && ++ appIcon.child._delegate.window == neededAppIcons[j].window); ++ ++ if (matchingAppIconIndex > 0 && matchingAppIconIndex != currentPosition) { ++ //moved icon, reposition it ++ this._box.remove_child(currentAppIcons[matchingAppIconIndex]); ++ this._box.insert_child_at_index(currentAppIcons[matchingAppIconIndex], currentPosition); ++ } else if (matchingAppIconIndex < 0) { ++ //the icon doesn't exist yet, create a new one ++ let newAppIcon = this._createAppItem(neededAppIcons[j].app, neededAppIcons[j].window, neededAppIcons[j].isLauncher); ++ ++ this._box.insert_child_at_index(newAppIcon, currentPosition); ++ currentAppIcons.splice(currentPosition, 0, newAppIcon); ++ ++ // Skip animations on first run when adding the initial set ++ // of items, to avoid all items zooming in at once ++ newAppIcon.show(this._shownInitially); ++ } ++ ++ ++currentPosition; ++ } ++ } ++ ++ this._adjustIconSize(); ++ ++ // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 ++ // Without it, StBoxLayout may use a stale size cache ++ this._box.queue_relayout(); ++ ++ // This is required for icon reordering when the scrollview is used. ++ this._updateAppIcons(); ++ ++ // This will update the size, and the corresponding number for each icon on the primary panel ++ if (this.dtpPanel.isPrimary) { ++ this._updateNumberOverlay(); ++ } ++ ++ this._shownInitially = true; ++ }, ++ ++ _checkIfShowingRunningApps: function() { ++ return Me.settings.get_boolean('show-running-apps'); ++ }, ++ ++ _checkIfShowingFavorites: function() { ++ return Me.settings.get_boolean('show-favorites') && ++ (this.dtpPanel.isPrimary || Me.settings.get_boolean('show-favorites-all-monitors')); ++ }, ++ ++ _getRunningApps: function() { ++ let tracker = Shell.WindowTracker.get_default(); ++ let windows = global.get_window_actors(); ++ let apps = []; ++ ++ for (let i = 0, l = windows.length; i < l; ++i) { ++ let app = tracker.get_window_app(windows[i].metaWindow); ++ ++ if (app && apps.indexOf(app) < 0) { ++ apps.push(app); ++ } ++ } ++ ++ return apps; ++ }, ++ ++ _createAppInfos: function(apps, defaultWindows, defaultIsLauncher) { ++ return apps.map(app => ({ ++ app: app, ++ isLauncher: defaultIsLauncher || false, ++ windows: defaultWindows || AppIcons.getInterestingWindows(app, this.dtpPanel.monitor) ++ .sort(sortWindowsCompareFunction) ++ })); ++ }, ++ ++ // Reset the displayed apps icon to mantain the correct order ++ resetAppIcons : function(geometryChange) { ++ let children = this._getTaskbarIcons(true); ++ ++ for (let i = 0; i < children.length; i++) { ++ let item = children[i]; ++ item.destroy(); ++ } ++ ++ // to avoid ugly animations, just suppress them like when taskbar is first loaded. ++ this._shownInitially = false; ++ this._redisplay(); ++ ++ if (geometryChange && this.dtpPanel.checkIfVertical()) { ++ this.previewMenu._updateClip(); ++ } ++ }, ++ ++ _updateNumberOverlay: function() { ++ let seenApps = {}; ++ let counter = 0; ++ ++ this._getAppIcons().forEach(function(icon) { ++ if (!seenApps[icon.app]) { ++ seenApps[icon.app] = 1; ++ counter++; ++ } ++ ++ if (counter <= 10) { ++ icon.setNumberOverlay(counter == 10 ? 0 : counter); ++ } else { ++ // No overlay after 10 ++ icon.setNumberOverlay(-1); ++ } ++ ++ icon.updateHotkeyNumberOverlay(); ++ }); ++ ++ if (Me.settings.get_boolean('hot-keys') && ++ Me.settings.get_string('hotkeys-overlay-combo') === 'ALWAYS') ++ this.toggleNumberOverlay(true); ++ }, ++ ++ toggleNumberOverlay: function(activate) { ++ let appIcons = this._getAppIcons(); ++ appIcons.forEach(function(icon) { ++ icon.toggleNumberOverlay(activate); ++ }); ++ }, ++ ++ _clearEmptyDropTarget: function() { ++ if (this._emptyDropTarget) { ++ this._emptyDropTarget.animateOutAndDestroy(); ++ this._emptyDropTarget = null; ++ } ++ }, ++ ++ handleDragOver: function(source, actor, x, y, time) { ++ if (source == Main.xdndHandler) ++ return DND.DragMotionResult.CONTINUE; ++ ++ // Don't allow favoriting of transient apps ++ if (source.app == null || source.app.is_window_backed()) ++ return DND.DragMotionResult.NO_DROP; ++ ++ if (!this._settings.is_writable('favorite-apps')) ++ return DND.DragMotionResult.NO_DROP; ++ ++ let sourceActor = source instanceof St.Widget ? source : source.actor; ++ let isVertical = this.dtpPanel.checkIfVertical(); ++ ++ if (!this._box.contains(sourceActor) && !source._dashItemContainer) { ++ //not an appIcon of the taskbar, probably from the applications view ++ source._dashItemContainer = new DragPlaceholderItem(source, this.iconSize, isVertical); ++ this._box.insert_child_above(source._dashItemContainer, null); ++ } ++ ++ let sizeProp = isVertical ? 'height' : 'width'; ++ let posProp = isVertical ? 'y' : 'x'; ++ let pos = isVertical ? y : x; ++ ++ let currentAppIcons = this._getAppIcons(); ++ let sourceIndex = currentAppIcons.indexOf(source); ++ let hoveredIndex = Utils.findIndex(currentAppIcons, ++ appIcon => pos >= appIcon._dashItemContainer[posProp] && ++ pos <= (appIcon._dashItemContainer[posProp] + appIcon._dashItemContainer[sizeProp])); ++ ++ if (!this._dragInfo) { ++ this._dragInfo = [sourceIndex, source]; ++ } ++ ++ if (hoveredIndex >= 0) { ++ let isLeft = pos < currentAppIcons[hoveredIndex]._dashItemContainer[posProp] + currentAppIcons[hoveredIndex]._dashItemContainer[sizeProp] * .5; ++ ++ // Don't allow positioning before or after self and between icons of same app ++ if (!(hoveredIndex === sourceIndex || ++ (isLeft && hoveredIndex - 1 == sourceIndex) || ++ (isLeft && hoveredIndex - 1 >= 0 && source.app != currentAppIcons[hoveredIndex - 1].app && ++ currentAppIcons[hoveredIndex - 1].app == currentAppIcons[hoveredIndex].app) || ++ (!isLeft && hoveredIndex + 1 == sourceIndex) || ++ (!isLeft && hoveredIndex + 1 < currentAppIcons.length && source.app != currentAppIcons[hoveredIndex + 1].app && ++ currentAppIcons[hoveredIndex + 1].app == currentAppIcons[hoveredIndex].app))) { ++ this._box.set_child_at_index(source._dashItemContainer, hoveredIndex); ++ ++ // Ensure the next and previous icon are visible when moving the icon ++ // (I assume there's room for both of them) ++ if (hoveredIndex > 1) ++ Utils.ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[hoveredIndex-1], this._scrollView._dtpFadeSize); ++ if (hoveredIndex < this._box.get_children().length-1) ++ Utils.ensureActorVisibleInScrollView(this._scrollView, this._box.get_children()[hoveredIndex+1], this._scrollView._dtpFadeSize); ++ } ++ } ++ ++ return this._dragInfo[0] !== sourceIndex ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.CONTINUE; ++ }, ++ ++ // Draggable target interface ++ acceptDrop : function(source, actor, x, y, time) { ++ // Don't allow favoriting of transient apps ++ if (!source.app || source.app.is_window_backed() || !this._settings.is_writable('favorite-apps')) { ++ return false; ++ } ++ ++ let appIcons = this._getAppIcons(); ++ let sourceIndex = appIcons.indexOf(source); ++ let usingLaunchers = !this.isGroupApps && Me.settings.get_boolean('group-apps-use-launchers'); ++ ++ // dragging the icon to its original position ++ if (this._dragInfo[0] === sourceIndex) { ++ return true; ++ } ++ ++ let appFavorites = AppFavorites.getAppFavorites(); ++ let sourceAppId = source.app.get_id(); ++ let appIsFavorite = appFavorites.isFavorite(sourceAppId); ++ let replacingIndex = sourceIndex + (sourceIndex > this._dragInfo[0] ? -1 : 1); ++ let favoriteIndex = replacingIndex >= 0 ? appFavorites.getFavorites().indexOf(appIcons[replacingIndex].app) : 0; ++ let sameApps = appIcons.filter(a => a != source && a.app == source.app); ++ let showingFavorites = this._checkIfShowingFavorites(); ++ let favoritesCount = 0; ++ let position = 0; ++ let interestingWindows = {}; ++ let getAppWindows = app => { ++ if (!interestingWindows[app]) { ++ interestingWindows[app] = AppIcons.getInterestingWindows(app, this.dtpPanel.monitor); ++ } ++ ++ let appWindows = interestingWindows[app]; //prevents "reference to undefined property Symbol.toPrimitive" warning ++ return appWindows; ++ }; ++ ++ if (sameApps.length && ++ ((!appIcons[sourceIndex - 1] || appIcons[sourceIndex - 1].app !== source.app) && ++ (!appIcons[sourceIndex + 1] || appIcons[sourceIndex + 1].app !== source.app))) { ++ appIcons.splice(appIcons.indexOf(sameApps[0]), sameApps.length); ++ Array.prototype.splice.apply(appIcons, [sourceIndex + 1, 0].concat(sameApps)); ++ } ++ ++ for (let i = 0, l = appIcons.length; i < l; ++i) { ++ let windows = []; ++ ++ if (!usingLaunchers || (!source.isLauncher && !appIcons[i].isLauncher)) { ++ windows = appIcons[i].window ? [appIcons[i].window] : getAppWindows(appIcons[i].app); ++ } ++ ++ windows.forEach(w => w._dtpPosition = position++); ++ ++ if (showingFavorites && ++ ((usingLaunchers && appIcons[i].isLauncher) || ++ (!usingLaunchers && appFavorites.isFavorite(appIcons[i].app.get_id())))) { ++ ++favoritesCount; ++ } ++ } ++ ++ if (sourceIndex < favoritesCount) { ++ if (appIsFavorite) { ++ appFavorites.moveFavoriteToPos(sourceAppId, favoriteIndex); ++ } else { ++ appFavorites.addFavoriteAtPos(sourceAppId, favoriteIndex); ++ } ++ } else if (appIsFavorite && showingFavorites && (!usingLaunchers || source.isLauncher)) { ++ appFavorites.removeFavorite(sourceAppId); ++ } ++ ++ appFavorites.emit('changed'); ++ ++ return true; ++ }, ++ ++ _onShowAppsButtonToggled: function() { ++ // Sync the status of the default appButtons. Only if the two statuses are ++ // different, that means the user interacted with the extension provided ++ // application button, cutomize the behaviour. Otherwise the shell has changed the ++ // status (due to the _syncShowAppsButtonToggled function below) and it ++ // has already performed the desired action. ++ ++ let animate = Me.settings.get_boolean('animate-show-apps'); ++ let selector = Main.overview.viewSelector; ++ ++ if (selector._showAppsButton.checked !== this.showAppsButton.checked) { ++ // find visible view ++ let visibleView; ++ Utils.getAppDisplayViews().every(function(v, index) { ++ if (v.view.actor.visible) { ++ visibleView = index; ++ return false; ++ } ++ else ++ return true; ++ }); ++ ++ if (this.showAppsButton.checked) { ++ if (Me.settings.get_boolean('show-apps-override-escape')) { ++ //override escape key to return to the desktop when entering the overview using the showapps button ++ Main.overview.viewSelector._onStageKeyPress = function(actor, event) { ++ if (Main.modalCount == 1 && event.get_key_symbol() === Clutter.KEY_Escape) { ++ this._searchActive ? this.reset() : Main.overview.hide(); ++ ++ return Clutter.EVENT_STOP; ++ } ++ ++ return this.__proto__._onStageKeyPress.call(this, actor, event); ++ }; ++ } ++ ++ // force spring animation triggering.By default the animation only ++ // runs if we are already inside the overview. ++ if (!Main.overview._shown) { ++ this.forcedOverview = true; ++ let grid = Utils.getAppDisplayViews()[visibleView].view._grid; ++ let onShownCb; ++ let overviewSignal = Config.PACKAGE_VERSION > '3.38.1' ? 'showing' : 'shown'; ++ let overviewShowingId = Main.overview.connect(overviewSignal, () => { ++ Main.overview.disconnect(overviewShowingId); ++ onShownCb(); ++ }); ++ ++ if (animate) { ++ // Animate in the the appview, hide the appGrid to avoiud flashing ++ // Go to the appView before entering the overview, skipping the workspaces. ++ // Do this manually avoiding opacity in transitions so that the setting of the opacity ++ // to 0 doesn't get overwritten. ++ Main.overview.viewSelector._activePage.hide(); ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._appsPage; ++ Main.overview.viewSelector._activePage.show(); ++ grid.actor.opacity = 0; ++ ++ // The animation has to be trigered manually because the AppDisplay.animate ++ // method is waiting for an allocation not happening, as we skip the workspace view ++ // and the appgrid could already be allocated from previous shown. ++ // It has to be triggered after the overview is shown as wrong coordinates are obtained ++ // otherwise. ++ onShownCb = () => Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ grid.actor.opacity = 255; ++ grid.animateSpring(IconGrid.AnimationDirection.IN, this.showAppsButton); ++ }); ++ } else { ++ Main.overview.viewSelector._activePage = Main.overview.viewSelector._appsPage; ++ Main.overview.viewSelector._activePage.show(); ++ onShownCb = () => grid.emit('animation-done'); ++ } ++ } ++ ++ //temporarily use as primary the monitor on which the showapps btn was clicked, this is ++ //restored by the panel when exiting the overview ++ this.dtpPanel.panelManager.setFocusedMonitor(this.dtpPanel.monitor); ++ ++ let overviewHiddenId = Main.overview.connect('hidden', () => { ++ Main.overview.disconnect(overviewHiddenId); ++ delete Main.overview.viewSelector._onStageKeyPress; ++ }); ++ ++ // Finally show the overview ++ selector._showAppsButton.checked = true; ++ Main.overview.show(); ++ } ++ else { ++ if (this.forcedOverview) { ++ // force exiting overview if needed ++ ++ if (animate) { ++ // Manually trigger springout animation without activating the ++ // workspaceView to avoid the zoomout animation. Hide the appPage ++ // onComplete to avoid ugly flashing of original icons. ++ let view = Utils.getAppDisplayViews()[visibleView].view; ++ view.animate(IconGrid.AnimationDirection.OUT, Lang.bind(this, function() { ++ Main.overview.viewSelector._appsPage.hide(); ++ Main.overview.hide(); ++ selector._showAppsButton.checked = false; ++ this.forcedOverview = false; ++ })); ++ } ++ else { ++ Main.overview.hide(); ++ this.forcedOverview = false; ++ } ++ } ++ else { ++ selector._showAppsButton.checked = false; ++ this.forcedOverview = false; ++ } ++ } ++ } ++ }, ++ ++ _syncShowAppsButtonToggled: function() { ++ let status = Main.overview.viewSelector._showAppsButton.checked; ++ if (this.showAppsButton.checked !== status) ++ this.showAppsButton.checked = status; ++ }, ++ ++ showShowAppsButton: function() { ++ this.showAppsButton.visible = true; ++ this.showAppsButton.set_width(-1); ++ this.showAppsButton.set_height(-1); ++ }, ++ ++ popupFocusedAppSecondaryMenu: function() { ++ let appIcons = this._getAppIcons(); ++ let tracker = Shell.WindowTracker.get_default(); ++ ++ for(let i in appIcons) { ++ if(appIcons[i].app == tracker.focus_app) { ++ let appIcon = appIcons[i]; ++ if(appIcon._menu && appIcon._menu.isOpen) ++ appIcon._menu.close(); ++ else ++ appIcon.popupMenu(); ++ ++ appIcon.sync_hover(); ++ break; ++ } ++ } ++ }, ++}); ++ ++Signals.addSignalMethods(taskbar.prototype); ++ ++const CloneContainerConstraint = Utils.defineClass({ ++ Name: 'DashToPanel-CloneContainerConstraint', ++ Extends: Clutter.BindConstraint, ++ ++ vfunc_update_allocation: function(actor, actorBox) { ++ if (!this.source) ++ return; ++ ++ let [stageX, stageY] = this.source.get_transformed_position(); ++ let [width, height] = this.source.get_transformed_size(); ++ ++ actorBox.set_origin(stageX, stageY); ++ actorBox.set_size(width, height); ++ }, ++}); ++ ++const TaskbarItemContainer = Utils.defineClass({ ++ Name: 'DashToPanel-TaskbarItemContainer', ++ Extends: Dash.DashItemContainer, ++ ++ vfunc_allocate: function(box, flags) { ++ if (this.child == null) ++ return; ++ ++ Utils.setAllocation(this, box, flags); ++ ++ let availWidth = box.x2 - box.x1; ++ let availHeight = box.y2 - box.y1; ++ let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] = this.child.get_preferred_size(); ++ let [childScaleX, childScaleY] = this.child.get_scale(); ++ ++ let childWidth = Math.min(natChildWidth * childScaleX, availWidth); ++ let childHeight = Math.min(natChildHeight * childScaleY, availHeight); ++ let childBox = new Clutter.ActorBox(); ++ ++ childBox.x1 = (availWidth - childWidth) / 2; ++ childBox.y1 = (availHeight - childHeight) / 2; ++ childBox.x2 = childBox.x1 + childWidth; ++ childBox.y2 = childBox.y1 + childHeight; ++ ++ Utils.allocate(this.child, childBox, flags); ++ }, ++ ++ // In case appIcon is removed from the taskbar while it is hovered, ++ // restore opacity before dashItemContainer.animateOutAndDestroy does the destroy animation. ++ animateOutAndDestroy: function() { ++ if (this._raisedClone) { ++ this._raisedClone.source.opacity = 255; ++ this._raisedClone.destroy(); ++ } ++ ++ this.callParent('animateOutAndDestroy'); ++ }, ++ ++ // For ItemShowLabel ++ _getIconAnimationOffset: function() { ++ if (!Me.settings.get_boolean('animate-appicon-hover')) ++ return 0; ++ ++ let travel = iconAnimationSettings.travel; ++ let zoom = iconAnimationSettings.zoom; ++ return this._dtpPanel.dtpSize * (travel + (zoom - 1) / 2); ++ }, ++ ++ _updateCloneContainerPosition: function(cloneContainer) { ++ let [stageX, stageY] = this.get_transformed_position(); ++ ++ if (Config.PACKAGE_VERSION >= '3.36') ++ cloneContainer.set_position(stageX - this.translation_x, stageY - this.translation_y); ++ else ++ cloneContainer.set_position(stageX, stageY); ++ }, ++ ++ _createRaisedClone: function() { ++ let [width, height] = this.get_transformed_size(); ++ ++ // "clone" of this child (appIcon actor) ++ let cloneButton = this.child._delegate.getCloneButton(); ++ ++ // "clone" of this (taskbarItemContainer) ++ let cloneContainer = new St.Bin({ ++ child: cloneButton, ++ width: width, height: height, ++ reactive: false, ++ }); ++ ++ this._updateCloneContainerPosition(cloneContainer); ++ ++ // For the stretch animation ++ if (Config.PACKAGE_VERSION >= '3.36') { ++ let boundProperty = this._dtpPanel.checkIfVertical() ? 'translation_y' : 'translation_x'; ++ this.bind_property(boundProperty, cloneContainer, boundProperty, GObject.BindingFlags.SYNC_CREATE); ++ } else { ++ let constraint = new CloneContainerConstraint({ source: this }); ++ cloneContainer.add_constraint(constraint); ++ } ++ ++ // The clone follows its source when the taskbar is scrolled. ++ let taskbarScrollView = this.get_parent().get_parent(); ++ let adjustment = this._dtpPanel.checkIfVertical() ? taskbarScrollView.vscroll.get_adjustment() : taskbarScrollView.hscroll.get_adjustment(); ++ let adjustmentChangedId = adjustment.connect('notify::value', () => this._updateCloneContainerPosition(cloneContainer)); ++ ++ // Update clone position when an item is added to / removed from the taskbar. ++ let taskbarBox = this.get_parent(); ++ let taskbarBoxAllocationChangedId = taskbarBox.connect('notify::allocation', () => this._updateCloneContainerPosition(cloneContainer)); ++ ++ // The clone itself ++ this._raisedClone = cloneButton.child; ++ this._raisedClone.connect('destroy', () => { ++ adjustment.disconnect(adjustmentChangedId); ++ taskbarBox.disconnect(taskbarBoxAllocationChangedId); ++ Mainloop.idle_add(() => cloneContainer.destroy()); ++ delete this._raisedClone; ++ }); ++ ++ this._raisedClone.source.opacity = 0; ++ Main.uiGroup.add_actor(cloneContainer); ++ }, ++ ++ // Animate the clone. ++ // AppIcon actors cannot go outside the taskbar so the animation is done with a clone. ++ // If level is zero, the clone is dropped and destroyed. ++ raise: function(level) { ++ if (this._raisedClone) ++ Utils.stopAnimations(this._raisedClone); ++ else if (level) ++ this._createRaisedClone(); ++ else ++ return; ++ ++ let panelPosition = this._dtpPanel.getPosition(); ++ let panelElementPositions = this._dtpPanel.panelManager.panelsElementPositions[this._dtpPanel.monitor.index] || Pos.defaults; ++ let taskbarPosition = panelElementPositions.filter(pos => pos.element == 'taskbar')[0].position; ++ ++ let vertical = panelPosition == St.Side.LEFT || panelPosition == St.Side.RIGHT; ++ let translationDirection = panelPosition == St.Side.TOP || panelPosition == St.Side.LEFT ? 1 : -1; ++ let rotationDirection; ++ if (panelPosition == St.Side.LEFT || taskbarPosition == Pos.STACKED_TL) ++ rotationDirection = -1; ++ else if (panelPosition == St.Side.RIGHT || taskbarPosition == Pos.STACKED_BR) ++ rotationDirection = 1; ++ else { ++ let items = this.get_parent().get_children(); ++ let index = items.indexOf(this); ++ rotationDirection = (index - (items.length - 1) / 2) / ((items.length - 1) / 2); ++ } ++ ++ let duration = iconAnimationSettings.duration / 1000; ++ let rotation = iconAnimationSettings.rotation; ++ let travel = iconAnimationSettings.travel; ++ let zoom = iconAnimationSettings.zoom; ++ ++ // level is about 1 for the icon that is hovered, less for others. ++ // time depends on the translation to do. ++ let [width, height] = this._raisedClone.source.get_transformed_size(); ++ let translationMax = (vertical ? width : height) * (travel + (zoom - 1) / 2); ++ let translationEnd = translationMax * level; ++ let translationDone = vertical ? this._raisedClone.translation_x : this._raisedClone.translation_y; ++ let translationTodo = Math.abs(translationEnd - translationDone); ++ let scale = 1 + (zoom - 1) * level; ++ let rotationAngleZ = rotationDirection * rotation * level; ++ let time = duration * translationTodo / translationMax; ++ ++ let options = { ++ scale_x: scale, scale_y: scale, ++ rotation_angle_z: rotationAngleZ, ++ time: time, ++ transition: 'easeOutQuad', ++ onComplete: () => { ++ if (!level) { ++ this._raisedClone.source.opacity = 255; ++ this._raisedClone.destroy(); ++ delete this._raisedClone; ++ } ++ }, ++ }; ++ options[vertical ? 'translation_x' : 'translation_y'] = translationDirection * translationEnd; ++ ++ Utils.animate(this._raisedClone, options); ++ }, ++ ++ // Animate this and cloneContainer, since cloneContainer translation is bound to this. ++ stretch: function(translation) { ++ let duration = iconAnimationSettings.duration / 1000; ++ let zoom = iconAnimationSettings.zoom; ++ let animatedProperty = this._dtpPanel.checkIfVertical() ? 'translation_y' : 'translation_x'; ++ let isShowing = this.opacity != 255 || this.child.opacity != 255; ++ ++ if (isShowing) { ++ // Do no stop the animation initiated in DashItemContainer.show. ++ this[animatedProperty] = zoom * translation; ++ } else { ++ let options = { ++ time: duration, ++ transition: 'easeOutQuad', ++ }; ++ options[animatedProperty] = zoom * translation; ++ ++ Utils.stopAnimations(this); ++ Utils.animate(this, options); ++ } ++ }, ++}); ++ ++var DragPlaceholderItem = Utils.defineClass({ ++ Name: 'DashToPanel-DragPlaceholderItem', ++ Extends: St.Widget, ++ ++ _init: function(appIcon, iconSize, isVertical) { ++ this.callParent('_init', { style: AppIcons.getIconContainerStyle(isVertical), layout_manager: new Clutter.BinLayout() }); ++ ++ this.child = { _delegate: appIcon }; ++ ++ this._clone = new Clutter.Clone({ ++ source: appIcon.icon._iconBin, ++ width: iconSize, ++ height: iconSize ++ }); ++ ++ this.add_actor(this._clone); ++ }, ++ ++ destroy: function() { ++ this._clone.destroy(); ++ this.callParent('destroy'); ++ }, ++}); ++ ++function getAppStableSequence(app, monitor) { ++ let windows = AppIcons.getInterestingWindows(app, monitor); ++ ++ return windows.reduce((prevWindow, window) => { ++ return Math.min(prevWindow, getWindowStableSequence(window)); ++ }, Infinity); ++} ++ ++function sortWindowsCompareFunction(windowA, windowB) { ++ return getWindowStableSequence(windowA) - getWindowStableSequence(windowB); ++} ++ ++function getWindowStableSequence(window) { ++ return ('_dtpPosition' in window ? window._dtpPosition : window.get_stable_sequence()); ++} +diff --git a/extensions/dash-to-panel/transparency.js b/extensions/dash-to-panel/transparency.js +new file mode 100644 +index 00000000..aa86d7ac +--- /dev/null ++++ b/extensions/dash-to-panel/transparency.js +@@ -0,0 +1,269 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Clutter = imports.gi.Clutter; ++const GdkPixbuf = imports.gi.GdkPixbuf; ++const Lang = imports.lang; ++const Main = imports.ui.main; ++const Meta = imports.gi.Meta; ++const St = imports.gi.St; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Panel = Me.imports.panel; ++const Proximity = Me.imports.proximity; ++const Utils = Me.imports.utils; ++ ++var DynamicTransparency = Utils.defineClass({ ++ Name: 'DashToPanel.DynamicTransparency', ++ ++ _init: function(dtpPanel) { ++ this._dtpPanel = dtpPanel; ++ this._proximityManager = dtpPanel.panelManager.proximityManager; ++ this._proximityWatchId = 0; ++ this._windowOverlap = false; ++ this.currentBackgroundColor = 0; ++ ++ this._initialPanelStyle = dtpPanel.panel.actor.get_style(); ++ ++ if (this._dtpPanel.geom.position == St.Side.TOP) { ++ this._initialPanelCornerStyle = dtpPanel.panel._leftCorner.actor.get_style(); ++ } ++ ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ this._bindSignals(); ++ ++ this._updateAnimationDuration(); ++ this._updateAllAndSet(); ++ this._updateProximityWatch(); ++ }, ++ ++ destroy: function() { ++ this._signalsHandler.destroy(); ++ this._proximityManager.removeWatch(this._proximityWatchId); ++ ++ this._dtpPanel.panel.actor.set_style(this._initialPanelStyle); ++ ++ if (this._dtpPanel.geom.position == St.Side.TOP) { ++ this._dtpPanel.panel._leftCorner.actor.set_style(this._initialPanelCornerStyle); ++ this._dtpPanel.panel._rightCorner.actor.set_style(this._initialPanelCornerStyle); ++ } ++ }, ++ ++ updateExternalStyle: function() { ++ this._updateComplementaryStyles(); ++ this._setBackground(); ++ }, ++ ++ _bindSignals: function() { ++ this._signalsHandler.add( ++ [ ++ Utils.getStageTheme(), ++ 'changed', ++ () => this._updateAllAndSet() ++ ], ++ [ ++ Main.overview, ++ [ ++ 'showing', ++ 'hiding' ++ ], ++ () => this._updateAlphaAndSet() ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::trans-use-custom-bg', ++ 'changed::trans-bg-color' ++ ], ++ () => this._updateColorAndSet() ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::trans-use-custom-opacity', ++ 'changed::trans-panel-opacity', ++ 'changed::trans-bg-color', ++ 'changed::trans-dynamic-anim-target', ++ 'changed::trans-use-dynamic-opacity' ++ ], ++ () => this._updateAlphaAndSet() ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::trans-use-custom-gradient', ++ 'changed::trans-gradient-top-color', ++ 'changed::trans-gradient-bottom-color', ++ 'changed::trans-gradient-top-opacity', ++ 'changed::trans-gradient-bottom-opacity' ++ ], ++ () => this._updateGradientAndSet() ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::trans-dynamic-behavior', ++ 'changed::trans-use-dynamic-opacity', ++ 'changed::trans-dynamic-distance' ++ ], ++ () => this._updateProximityWatch() ++ ], ++ [ ++ Me.settings, ++ 'changed::trans-dynamic-anim-time', ++ () => this._updateAnimationDuration() ++ ] ++ ); ++ }, ++ ++ _updateProximityWatch: function() { ++ this._proximityManager.removeWatch(this._proximityWatchId); ++ ++ if (Me.settings.get_boolean('trans-use-dynamic-opacity')) { ++ let isVertical = this._dtpPanel.checkIfVertical(); ++ let threshold = Me.settings.get_int('trans-dynamic-distance'); ++ ++ this._proximityWatchId = this._proximityManager.createWatch( ++ this._dtpPanel.panelBox.get_parent(), ++ Proximity.Mode[Me.settings.get_string('trans-dynamic-behavior')], ++ isVertical ? threshold : 0, ++ isVertical ? 0 : threshold, ++ overlap => { ++ this._windowOverlap = overlap; ++ this._updateAlphaAndSet(); ++ } ++ ); ++ } ++ }, ++ ++ _updateAnimationDuration: function() { ++ this.animationDuration = (Me.settings.get_int('trans-dynamic-anim-time') * 0.001) + 's;'; ++ }, ++ ++ _updateAllAndSet: function() { ++ let themeBackground = this._getThemeBackground(true); ++ ++ this._updateColor(themeBackground); ++ this._updateAlpha(themeBackground); ++ this._updateComplementaryStyles(); ++ this._updateGradient(); ++ this._setBackground(); ++ this._setGradient(); ++ }, ++ ++ _updateColorAndSet: function() { ++ this._updateColor(); ++ this._setBackground(); ++ }, ++ ++ _updateAlphaAndSet: function() { ++ this._updateAlpha(); ++ this._setBackground(); ++ }, ++ ++ _updateGradientAndSet: function() { ++ this._updateGradient(); ++ this._setGradient(); ++ }, ++ ++ _updateComplementaryStyles: function() { ++ let panelThemeNode = this._dtpPanel.panel.actor.get_theme_node(); ++ ++ this._complementaryStyles = 'border-radius: ' + panelThemeNode.get_border_radius(0) + 'px;'; ++ }, ++ ++ _updateColor: function(themeBackground) { ++ this.backgroundColorRgb = Me.settings.get_boolean('trans-use-custom-bg') ? ++ Me.settings.get_string('trans-bg-color') : ++ (themeBackground || this._getThemeBackground()); ++ }, ++ ++ _updateAlpha: function(themeBackground) { ++ if (this._windowOverlap && !Main.overview.visibleTarget && Me.settings.get_boolean('trans-use-dynamic-opacity')) { ++ this.alpha = Me.settings.get_double('trans-dynamic-anim-target'); ++ } else { ++ this.alpha = Me.settings.get_boolean('trans-use-custom-opacity') ? ++ Me.settings.get_double('trans-panel-opacity') : ++ (themeBackground || this._getThemeBackground()).alpha * 0.003921569; // 1 / 255 = 0.003921569 ++ } ++ }, ++ ++ _updateGradient: function() { ++ this._gradientStyle = ''; ++ ++ if (Me.settings.get_boolean('trans-use-custom-gradient')) { ++ this._gradientStyle += 'background-gradient-direction: ' + (this._dtpPanel.checkIfVertical() ? 'horizontal;' : 'vertical;') + ++ 'background-gradient-start: ' + Utils.getrgbaColor(Me.settings.get_string('trans-gradient-top-color'), ++ Me.settings.get_double('trans-gradient-top-opacity')) + ++ 'background-gradient-end: ' + Utils.getrgbaColor(Me.settings.get_string('trans-gradient-bottom-color'), ++ Me.settings.get_double('trans-gradient-bottom-opacity')); ++ } ++ }, ++ ++ _setBackground: function() { ++ this.currentBackgroundColor = Utils.getrgbaColor(this.backgroundColorRgb, this.alpha); ++ ++ let transition = 'transition-duration:' + this.animationDuration; ++ let cornerStyle = '-panel-corner-background-color: ' + this.currentBackgroundColor + transition; ++ ++ this._dtpPanel.set_style('background-color: ' + this.currentBackgroundColor + transition + this._complementaryStyles); ++ ++ if (this._dtpPanel.geom.position == St.Side.TOP) { ++ this._dtpPanel.panel._leftCorner.actor.set_style(cornerStyle); ++ this._dtpPanel.panel._rightCorner.actor.set_style(cornerStyle); ++ } ++ }, ++ ++ _setGradient: function() { ++ this._dtpPanel.panel.actor.set_style( ++ 'background: none; ' + ++ 'border-image: none; ' + ++ 'background-image: none; ' + ++ this._gradientStyle + ++ 'transition-duration:' + this.animationDuration ++ ); ++ }, ++ ++ _getThemeBackground: function(reload) { ++ if (reload || !this._themeBackground) { ++ let fakePanel = new St.Bin({ name: 'panel' }); ++ Main.uiGroup.add_child(fakePanel); ++ let fakeTheme = fakePanel.get_theme_node() ++ this._themeBackground = this._getBackgroundImageColor(fakeTheme) || fakeTheme.get_background_color(); ++ Main.uiGroup.remove_child(fakePanel); ++ } ++ ++ return this._themeBackground; ++ }, ++ ++ _getBackgroundImageColor: function(theme) { ++ let bg = null; ++ ++ try { ++ let imageFile = theme.get_background_image() || theme.get_border_image().get_file(); ++ ++ if (imageFile) { ++ let imageBuf = GdkPixbuf.Pixbuf.new_from_file(imageFile.get_path()); ++ let pixels = imageBuf.get_pixels(); ++ ++ bg = { red: pixels[0], green: pixels[1], blue: pixels[2], alpha: pixels[3] }; ++ } ++ } catch (error) {} ++ ++ return bg; ++ } ++}); +\ No newline at end of file +diff --git a/extensions/dash-to-panel/utils.js b/extensions/dash-to-panel/utils.js +new file mode 100644 +index 00000000..51d056d3 +--- /dev/null ++++ b/extensions/dash-to-panel/utils.js +@@ -0,0 +1,1035 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * ++ * Credits: ++ * This file is based on code from the Dash to Dock extension by micheleg ++ * and code from the Taskbar extension by Zorin OS ++ * Some code was also adapted from the upstream Gnome Shell source code. ++ */ ++ ++const Clutter = imports.gi.Clutter; ++const Config = imports.misc.config; ++const GdkPixbuf = imports.gi.GdkPixbuf; ++const Gi = imports._gi; ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const GObject = imports.gi.GObject; ++const Gtk = imports.gi.Gtk; ++const Meta = imports.gi.Meta; ++const Shell = imports.gi.Shell; ++const St = imports.gi.St; ++const Mainloop = imports.mainloop; ++const Main = imports.ui.main; ++const MessageTray = imports.ui.messageTray; ++const Util = imports.misc.util; ++ ++var TRANSLATION_DOMAIN = imports.misc.extensionUtils.getCurrentExtension().metadata['gettext-domain']; ++var SCROLL_TIME = Util.SCROLL_TIME / (Util.SCROLL_TIME > 1 ? 1000 : 1); ++ ++//Clutter implicit animations are available since 3.34 ++//prefer those over Tweener if available ++if (Config.PACKAGE_VERSION < '3.34') { ++ var Tweener = imports.ui.tweener; ++} ++ ++var defineClass = function (classDef) { ++ let parentProto = classDef.Extends ? classDef.Extends.prototype : null; ++ ++ if (Config.PACKAGE_VERSION < '3.31.9') { ++ if (parentProto && (classDef.Extends.name || classDef.Extends.toString()).indexOf('DashToPanel.') < 0) { ++ classDef.callParent = function() { ++ let args = Array.prototype.slice.call(arguments); ++ let func = args.shift(); ++ ++ classDef.Extends.prototype[func].apply(this, args); ++ }; ++ } ++ ++ return new imports.lang.Class(classDef); ++ } ++ ++ let isGObject = parentProto instanceof GObject.Object; ++ let needsSuper = parentProto && !isGObject; ++ let getParentArgs = function(args) { ++ let parentArgs = []; ++ ++ (classDef.ParentConstrParams || parentArgs).forEach(p => { ++ if (p.constructor === Array) { ++ let param = args[p[0]]; ++ ++ parentArgs.push(p[1] ? param[p[1]] : param); ++ } else { ++ parentArgs.push(p); ++ } ++ }); ++ ++ return parentArgs; ++ }; ++ ++ let C = eval( ++ '(class C ' + (needsSuper ? 'extends Object' : '') + ' { ' + ++ ' constructor(...args) { ' + ++ (needsSuper ? 'super(...getParentArgs(args));' : '') + ++ (needsSuper || !parentProto ? 'this._init(...args);' : '') + ++ ' }' + ++ ' callParent(...args) { ' + ++ ' let func = args.shift(); ' + ++ ' if (!(func === \'_init\' && needsSuper))' + ++ ' super[func](...args); ' + ++ ' }' + ++ '})' ++ ); ++ ++ if (parentProto) { ++ Object.setPrototypeOf(C.prototype, parentProto); ++ Object.setPrototypeOf(C, classDef.Extends); ++ } ++ ++ Object.defineProperty(C, 'name', { value: classDef.Name }); ++ Object.keys(classDef) ++ .filter(k => classDef.hasOwnProperty(k) && classDef[k] instanceof Function) ++ .forEach(k => C.prototype[k] = classDef[k]); ++ ++ if (isGObject) { ++ C = GObject.registerClass({ Signals: classDef.Signals || {} }, C); ++ } ++ ++ return C; ++}; ++ ++// simplify global signals and function injections handling ++// abstract class ++var BasicHandler = defineClass({ ++ Name: 'DashToPanel.BasicHandler', ++ ++ _init: function(){ ++ this._storage = new Object(); ++ }, ++ ++ add: function(/*unlimited 3-long array arguments*/){ ++ ++ // convert arguments object to array, concatenate with generic ++ let args = [].concat('generic', [].slice.call(arguments)); ++ // call addWithLabel with ags as if they were passed arguments ++ this.addWithLabel.apply(this, args); ++ }, ++ ++ destroy: function() { ++ for( let label in this._storage ) ++ this.removeWithLabel(label); ++ }, ++ ++ addWithLabel: function( label /* plus unlimited 3-long array arguments*/) { ++ ++ if(this._storage[label] == undefined) ++ this._storage[label] = new Array(); ++ ++ // skip first element of the arguments ++ for( let i = 1; i < arguments.length; i++ ) { ++ let item = this._storage[label]; ++ let handlers = this._create(arguments[i]); ++ ++ for (let j = 0, l = handlers.length; j < l; ++j) { ++ item.push(handlers[j]); ++ } ++ } ++ ++ }, ++ ++ removeWithLabel: function(label){ ++ ++ if(this._storage[label]) { ++ for( let i = 0; i < this._storage[label].length; i++ ) { ++ this._remove(this._storage[label][i]); ++ } ++ ++ delete this._storage[label]; ++ } ++ }, ++ ++ /* Virtual methods to be implemented by subclass */ ++ // create single element to be stored in the storage structure ++ _create: function(item){ ++ throw new Error('no implementation of _create in ' + this); ++ }, ++ ++ // correctly delete single element ++ _remove: function(item){ ++ throw new Error('no implementation of _remove in ' + this); ++ } ++}); ++ ++// Manage global signals ++var GlobalSignalsHandler = defineClass({ ++ Name: 'DashToPanel.GlobalSignalsHandler', ++ Extends: BasicHandler, ++ ++ _create: function(item) { ++ let handlers = []; ++ ++ item[1] = [].concat(item[1]); ++ ++ for (let i = 0, l = item[1].length; i < l; ++i) { ++ let object = item[0]; ++ let event = item[1][i]; ++ let callback = item[2] ++ let id = object.connect(event, callback); ++ ++ handlers.push([object, id]); ++ } ++ ++ return handlers; ++ }, ++ ++ _remove: function(item){ ++ item[0].disconnect(item[1]); ++ } ++}); ++ ++/** ++ * Manage function injection: both instances and prototype can be overridden ++ * and restored ++ */ ++var InjectionsHandler = defineClass({ ++ Name: 'DashToPanel.InjectionsHandler', ++ Extends: BasicHandler, ++ ++ _create: function(item) { ++ let object = item[0]; ++ let name = item[1]; ++ let injectedFunction = item[2]; ++ let original = object[name]; ++ ++ object[name] = injectedFunction; ++ return [[object, name, injectedFunction, original]]; ++ }, ++ ++ _remove: function(item) { ++ let object = item[0]; ++ let name = item[1]; ++ let original = item[3]; ++ object[name] = original; ++ } ++}); ++ ++/** ++ * Manage timeouts: the added timeouts have their id reset on completion ++ */ ++var TimeoutsHandler = defineClass({ ++ Name: 'DashToPanel.TimeoutsHandler', ++ Extends: BasicHandler, ++ ++ _create: function(item) { ++ let name = item[0]; ++ let delay = item[1]; ++ let timeoutHandler = item[2]; ++ ++ this._remove(item); ++ ++ this[name] = Mainloop.timeout_add(delay, () => { ++ this[name] = 0; ++ timeoutHandler(); ++ }); ++ ++ return [[name]]; ++ }, ++ ++ remove: function(name) { ++ this._remove([name]) ++ }, ++ ++ _remove: function(item) { ++ let name = item[0]; ++ ++ if (this[name]) { ++ Mainloop.source_remove(this[name]); ++ this[name] = 0; ++ } ++ }, ++ ++ getId: function(name) { ++ return this[name] ? this[name] : 0; ++ } ++}); ++ ++// This is wrapper to maintain compatibility with GNOME-Shell 3.30+ as well as ++// previous versions. ++var DisplayWrapper = { ++ getScreen: function() { ++ return global.screen || global.display; ++ }, ++ ++ getWorkspaceManager: function() { ++ return global.screen || global.workspace_manager; ++ }, ++ ++ getMonitorManager: function() { ++ return global.screen || Meta.MonitorManager.get(); ++ } ++}; ++ ++var getCurrentWorkspace = function() { ++ return DisplayWrapper.getWorkspaceManager().get_active_workspace(); ++}; ++ ++var getWorkspaceByIndex = function(index) { ++ return DisplayWrapper.getWorkspaceManager().get_workspace_by_index(index); ++}; ++ ++var getWorkspaceCount = function() { ++ return DisplayWrapper.getWorkspaceManager().n_workspaces; ++}; ++ ++var getStageTheme = function() { ++ return St.ThemeContext.get_for_stage(global.stage); ++}; ++ ++var getScaleFactor = function() { ++ return getStageTheme().scale_factor || 1; ++}; ++ ++var getAppDisplayViews = function() { ++ //gnome-shell 3.38 only has one view and it is now the appDisplay ++ return Main.overview.viewSelector.appDisplay._views || [{ view: Main.overview.viewSelector.appDisplay }]; ++}; ++ ++var findIndex = function(array, predicate) { ++ if (Array.prototype.findIndex) { ++ return array.findIndex(predicate); ++ } ++ ++ for (let i = 0, l = array.length; i < l; ++i) { ++ if (predicate(array[i])) { ++ return i; ++ } ++ } ++ ++ return -1; ++}; ++ ++var find = function(array, predicate) { ++ let index = findIndex(array, predicate); ++ ++ if (index > -1) { ++ return array[index]; ++ } ++}; ++ ++var mergeObjects = function(main, bck) { ++ for (var prop in bck) { ++ if (!main.hasOwnProperty(prop) && bck.hasOwnProperty(prop)) { ++ main[prop] = bck[prop]; ++ } ++ } ++ ++ return main; ++}; ++ ++var hookVfunc = function(proto, symbol, func) { ++ if (Gi.hook_up_vfunc_symbol) { ++ //gjs > 1.53.3 ++ proto[Gi.hook_up_vfunc_symbol](symbol, func); ++ } else { ++ //On older gjs, this is how to hook vfunc. It is buggy and can't be used reliably to replace ++ //already hooked functions. Since it's our only use for it, disabled for now (and probably forever) ++ //Gi.hook_up_vfunc(proto, symbol, func); ++ } ++}; ++ ++var wrapActor = function(actor) { ++ if (actor) { ++ Object.defineProperty(actor, 'actor', { ++ value: actor instanceof Clutter.Actor ? actor : actor.actor ++ }); ++ } ++}; ++ ++var getTransformedAllocation = function(actor) { ++ if (Config.PACKAGE_VERSION < '3.37') { ++ return Shell.util_get_transformed_allocation(actor); ++ } ++ ++ let extents = actor.get_transformed_extents(); ++ let topLeft = extents.get_top_left(); ++ let bottomRight = extents.get_bottom_right(); ++ ++ return { x1: topLeft.x, x2: bottomRight.x, y1: topLeft.y, y2: bottomRight.y }; ++}; ++ ++var allocate = function(actor, box, flags, useParent) { ++ let allocateObj = useParent ? actor.__proto__ : actor; ++ ++ allocateObj.allocate.apply(actor, getAllocationParams(box, flags)); ++}; ++ ++var setAllocation = function(actor, box, flags) { ++ actor.set_allocation.apply(actor, getAllocationParams(box, flags)); ++}; ++ ++var getAllocationParams = function(box, flags) { ++ let params = [box]; ++ ++ if (Config.PACKAGE_VERSION < '3.37') { ++ params.push(flags); ++ } ++ ++ return params; ++}; ++ ++var setClip = function(actor, x, y, width, height) { ++ actor.set_clip(0, 0, width, height); ++ actor.set_position(x, y); ++ actor.set_size(width, height); ++}; ++ ++var addKeybinding = function(key, settings, handler, modes) { ++ if (!Main.wm._allowedKeybindings[key]) { ++ Main.wm.addKeybinding( ++ key, ++ settings, ++ Meta.KeyBindingFlags.NONE, ++ modes || (Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW), ++ handler ++ ); ++ } ++}; ++ ++var removeKeybinding = function(key) { ++ if (Main.wm._allowedKeybindings[key]) { ++ Main.wm.removeKeybinding(key); ++ } ++}; ++ ++var getrgbColor = function(color) { ++ color = typeof color === 'string' ? Clutter.color_from_string(color)[1] : color; ++ ++ return { red: color.red, green: color.green, blue: color.blue }; ++}; ++ ++var getrgbaColor = function(color, alpha, offset) { ++ if (alpha <= 0) { ++ return 'transparent; '; ++ } ++ ++ let rgb = getrgbColor(color); ++ ++ if (offset) { ++ ['red', 'green', 'blue'].forEach(k => { ++ rgb[k] = Math.min(255, Math.max(0, rgb[k] + offset)); ++ ++ if (rgb[k] == color[k]) { ++ rgb[k] = Math.min(255, Math.max(0, rgb[k] - offset)); ++ } ++ }); ++ } ++ ++ return 'rgba(' + rgb.red + ',' + rgb.green + ',' + rgb.blue + ',' + (Math.floor(alpha * 100) * 0.01) + '); ' ; ++}; ++ ++var checkIfColorIsBright = function(color) { ++ let rgb = getrgbColor(color); ++ let brightness = 0.2126 * rgb.red + 0.7152 * rgb.green + 0.0722 * rgb.blue; ++ ++ return brightness > 128; ++}; ++ ++var getMouseScrollDirection = function(event) { ++ let direction; ++ ++ switch (event.get_scroll_direction()) { ++ case Clutter.ScrollDirection.UP: ++ case Clutter.ScrollDirection.LEFT: ++ direction = 'up'; ++ break; ++ case Clutter.ScrollDirection.DOWN: ++ case Clutter.ScrollDirection.RIGHT: ++ direction = 'down'; ++ break; ++ } ++ ++ return direction; ++}; ++ ++var checkIfWindowHasTransient = function(window) { ++ let hasTransient; ++ ++ window.foreach_transient(t => !(hasTransient = true)); ++ ++ return hasTransient; ++}; ++ ++var activateSiblingWindow = function(windows, direction, startWindow) { ++ let windowIndex = windows.indexOf(global.display.focus_window); ++ let nextWindowIndex = windowIndex < 0 ? ++ startWindow ? windows.indexOf(startWindow) : 0 : ++ windowIndex + (direction == 'up' ? 1 : -1); ++ ++ if (nextWindowIndex == windows.length) { ++ nextWindowIndex = 0; ++ } else if (nextWindowIndex < 0) { ++ nextWindowIndex = windows.length - 1; ++ } ++ ++ if (windowIndex != nextWindowIndex) { ++ Main.activateWindow(windows[nextWindowIndex]); ++ } ++}; ++ ++var animateWindowOpacity = function(window, tweenOpts) { ++ //there currently is a mutter bug with the windowactor opacity, starting with 3.34 ++ //https://gitlab.gnome.org/GNOME/mutter/issues/836 ++ ++ if (Config.PACKAGE_VERSION > '3.35') { ++ //on 3.36, a workaround is to use the windowactor's child for the fade animation ++ //this leaves a "shadow" on the desktop, so the windowactor needs to be hidden ++ //when the animation is complete ++ let visible = tweenOpts.opacity > 0; ++ let windowActor = window; ++ ++ window = windowActor.get_first_child() || windowActor; ++ ++ if (!windowActor.visible && visible) { ++ window.opacity = 0; ++ windowActor.visible = visible; ++ } ++ ++ if (!visible) { ++ let initialOpacity = window.opacity; ++ ++ tweenOpts.onComplete = () => { ++ windowActor.visible = visible; ++ window.opacity = initialOpacity; ++ }; ++ } ++ } else if (Config.PACKAGE_VERSION > '3.33') { ++ //the workaround only works on 3.35+, so on 3.34, let's just hide the ++ //window without animation ++ return window.visible = (tweenOpts.opacity == 255); ++ } ++ ++ animate(window, tweenOpts); ++}; ++ ++var animate = function(actor, options) { ++ if (Tweener) { ++ return Tweener.addTween(actor, options); ++ } ++ ++ //to support both Tweener and Clutter animations, we use Tweener "time" ++ //and "delay" properties defined in seconds, as opposed to Clutter animations ++ //"duration" and "delay" which are defined in milliseconds ++ if (options.delay) { ++ options.delay = options.delay * 1000; ++ } ++ ++ options.duration = options.time * 1000; ++ delete options.time; ++ ++ if (options.transition) { ++ //map Tweener easing equations to Clutter animation modes ++ options.mode = { ++ 'easeInCubic': Clutter.AnimationMode.EASE_IN_CUBIC, ++ 'easeInOutCubic': Clutter.AnimationMode.EASE_IN_OUT_CUBIC, ++ 'easeInOutQuad': Clutter.AnimationMode.EASE_IN_OUT_QUAD, ++ 'easeOutQuad': Clutter.AnimationMode.EASE_OUT_QUAD ++ }[options.transition] || Clutter.AnimationMode.LINEAR; ++ ++ delete options.transition; ++ } ++ ++ let params = [options]; ++ ++ if ('value' in options && actor instanceof St.Adjustment) { ++ params.unshift(options.value); ++ delete options.value; ++ } ++ ++ actor.ease.apply(actor, params); ++} ++ ++var isAnimating = function(actor, prop) { ++ if (Tweener) { ++ return Tweener.isTweening(actor); ++ } ++ ++ return !!actor.get_transition(prop); ++} ++ ++var stopAnimations = function(actor) { ++ if (Tweener) { ++ return Tweener.removeTweens(actor); ++ } ++ ++ actor.remove_all_transitions(); ++} ++ ++var getIndicators = function(delegate) { ++ if (delegate instanceof St.BoxLayout) { ++ return delegate; ++ } ++ ++ return delegate.indicators; ++} ++ ++var getPoint = function(coords) { ++ if (Config.PACKAGE_VERSION > '3.35.1') { ++ return new imports.gi.Graphene.Point(coords); ++ } ++ ++ return new Clutter.Point(coords); ++} ++ ++var getPanelGhost = function() { ++ if (!Main.overview._panelGhost) { ++ return Main.overview._overview.get_first_child(); ++ } ++ ++ return Main.overview._panelGhost; ++} ++ ++var notify = function(text, iconName, action, isTransient) { ++ let source = new MessageTray.SystemNotificationSource(); ++ let notification = new MessageTray.Notification(source, 'Dash to Panel', text); ++ let notifyFunc = source.showNotification || source.notify; ++ ++ if (iconName) { ++ source.createIcon = function() { ++ return new St.Icon({ icon_name: iconName }); ++ }; ++ } ++ ++ if (action) { ++ if (!(action instanceof Array)) { ++ action = [action]; ++ } ++ ++ action.forEach(a => notification.addAction(a.text, a.func)); ++ } ++ ++ Main.messageTray.add(source); ++ ++ notification.setTransient(isTransient); ++ notifyFunc.call(source, notification); ++}; ++ ++/* ++ * This is a copy of the same function in utils.js, but also adjust horizontal scrolling ++ * and perform few further cheks on the current value to avoid changing the values when ++ * it would be clamp to the current one in any case. ++ * Return the amount of shift applied ++*/ ++var ensureActorVisibleInScrollView = function(scrollView, actor, fadeSize, onComplete) { ++ let vadjustment = scrollView.vscroll.adjustment; ++ let hadjustment = scrollView.hscroll.adjustment; ++ let [vvalue, vlower, vupper, vstepIncrement, vpageIncrement, vpageSize] = vadjustment.get_values(); ++ let [hvalue, hlower, hupper, hstepIncrement, hpageIncrement, hpageSize] = hadjustment.get_values(); ++ ++ let [hvalue0, vvalue0] = [hvalue, vvalue]; ++ ++ let voffset = fadeSize; ++ let hoffset = fadeSize; ++ ++ let box = actor.get_allocation_box(); ++ let y1 = box.y1, y2 = box.y2, x1 = box.x1, x2 = box.x2; ++ ++ let parent = actor.get_parent(); ++ while (parent != scrollView) { ++ if (!parent) ++ throw new Error("actor not in scroll view"); ++ ++ let box = parent.get_allocation_box(); ++ y1 += box.y1; ++ y2 += box.y1; ++ x1 += box.x1; ++ x2 += box.x1; ++ parent = parent.get_parent(); ++ } ++ ++ if (y1 < vvalue + voffset) ++ vvalue = Math.max(0, y1 - voffset); ++ else if (vvalue < vupper - vpageSize && y2 > vvalue + vpageSize - voffset) ++ vvalue = Math.min(vupper -vpageSize, y2 + voffset - vpageSize); ++ ++ if (x1 < hvalue + hoffset) ++ hvalue = Math.max(0, x1 - hoffset); ++ else if (hvalue < hupper - hpageSize && x2 > hvalue + hpageSize - hoffset) ++ hvalue = Math.min(hupper - hpageSize, x2 + hoffset - hpageSize); ++ ++ let tweenOpts = { ++ time: SCROLL_TIME, ++ onComplete: onComplete || (() => {}), ++ transition: 'easeOutQuad' ++ }; ++ ++ if (vvalue !== vvalue0) { ++ animate(vadjustment, mergeObjects(tweenOpts, { value: vvalue })); ++ } ++ ++ if (hvalue !== hvalue0) { ++ animate(hadjustment, mergeObjects(tweenOpts, { value: hvalue })); ++ } ++ ++ return [hvalue- hvalue0, vvalue - vvalue0]; ++} ++ ++/** ++ * ColorUtils is adapted from https://github.com/micheleg/dash-to-dock ++ */ ++var ColorUtils = { ++ colorLuminance: function(r, g, b, dlum) { ++ // Darken or brighten color by a fraction dlum ++ // Each rgb value is modified by the same fraction. ++ // Return "#rrggbb" strin ++ ++ let rgbString = '#'; ++ ++ rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(r*(1+dlum), 0), 255)), 2); ++ rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(g*(1+dlum), 0), 255)), 2); ++ rgbString += ColorUtils._decimalToHex(Math.round(Math.min(Math.max(b*(1+dlum), 0), 255)), 2); ++ ++ return rgbString; ++ }, ++ ++ _decimalToHex: function(d, padding) { ++ // Convert decimal to an hexadecimal string adding the desired padding ++ ++ let hex = d.toString(16); ++ while (hex.length < padding) ++ hex = '0'+ hex; ++ return hex; ++ }, ++ ++ HSVtoRGB: function(h, s, v) { ++ // Convert hsv ([0-1, 0-1, 0-1]) to rgb ([0-255, 0-255, 0-255]). ++ // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV ++ // here with h = [0,1] instead of [0, 360] ++ // Accept either (h,s,v) independently or {h:h, s:s, v:v} object. ++ // Return {r:r, g:g, b:b} object. ++ ++ if (arguments.length === 1) { ++ s = h.s; ++ v = h.v; ++ h = h.h; ++ } ++ ++ let r,g,b; ++ let c = v*s; ++ let h1 = h*6; ++ let x = c*(1 - Math.abs(h1 % 2 - 1)); ++ let m = v - c; ++ ++ if (h1 <=1) ++ r = c + m, g = x + m, b = m; ++ else if (h1 <=2) ++ r = x + m, g = c + m, b = m; ++ else if (h1 <=3) ++ r = m, g = c + m, b = x + m; ++ else if (h1 <=4) ++ r = m, g = x + m, b = c + m; ++ else if (h1 <=5) ++ r = x + m, g = m, b = c + m; ++ else ++ r = c + m, g = m, b = x + m; ++ ++ return { ++ r: Math.round(r * 255), ++ g: Math.round(g * 255), ++ b: Math.round(b * 255) ++ }; ++ }, ++ ++ RGBtoHSV: function(r, g, b) { ++ // Convert rgb ([0-255, 0-255, 0-255]) to hsv ([0-1, 0-1, 0-1]). ++ // Following algorithm in https://en.wikipedia.org/wiki/HSL_and_HSV ++ // here with h = [0,1] instead of [0, 360] ++ // Accept either (r,g,b) independently or {r:r, g:g, b:b} object. ++ // Return {h:h, s:s, v:v} object. ++ ++ if (arguments.length === 1) { ++ r = r.r; ++ g = r.g; ++ b = r.b; ++ } ++ ++ let h,s,v; ++ ++ let M = Math.max(r, g, b); ++ let m = Math.min(r, g, b); ++ let c = M - m; ++ ++ if (c == 0) ++ h = 0; ++ else if (M == r) ++ h = ((g-b)/c) % 6; ++ else if (M == g) ++ h = (b-r)/c + 2; ++ else ++ h = (r-g)/c + 4; ++ ++ h = h/6; ++ v = M/255; ++ if (M !== 0) ++ s = c/M; ++ else ++ s = 0; ++ ++ return {h: h, s: s, v: v}; ++ } ++}; ++ ++/** ++ * DominantColorExtractor is adapted from https://github.com/micheleg/dash-to-dock ++ */ ++let themeLoader = null; ++let iconCacheMap = new Map(); ++const MAX_CACHED_ITEMS = 1000; ++const BATCH_SIZE_TO_DELETE = 50; ++const DOMINANT_COLOR_ICON_SIZE = 64; ++ ++var DominantColorExtractor = defineClass({ ++ Name: 'DashToPanel.DominantColorExtractor', ++ ++ _init: function(app){ ++ this._app = app; ++ }, ++ ++ /** ++ * Try to get the pixel buffer for the current icon, if not fail gracefully ++ */ ++ _getIconPixBuf: function() { ++ let iconTexture = this._app.create_icon_texture(16); ++ ++ if (themeLoader === null) { ++ let ifaceSettings = new Gio.Settings({ schema: "org.gnome.desktop.interface" }); ++ ++ themeLoader = new Gtk.IconTheme(), ++ themeLoader.set_custom_theme(ifaceSettings.get_string('icon-theme')); // Make sure the correct theme is loaded ++ } ++ ++ // Unable to load the icon texture, use fallback ++ if (iconTexture instanceof St.Icon === false) { ++ return null; ++ } ++ ++ iconTexture = iconTexture.get_gicon(); ++ ++ // Unable to load the icon texture, use fallback ++ if (iconTexture === null) { ++ return null; ++ } ++ ++ if (iconTexture instanceof Gio.FileIcon) { ++ // Use GdkPixBuf to load the pixel buffer from the provided file path ++ return GdkPixbuf.Pixbuf.new_from_file(iconTexture.get_file().get_path()); ++ } ++ ++ // Get the pixel buffer from the icon theme ++ let icon_info = themeLoader.lookup_icon(iconTexture.get_names()[0], DOMINANT_COLOR_ICON_SIZE, 0); ++ if (icon_info !== null) ++ return icon_info.load_icon(); ++ else ++ return null; ++ }, ++ ++ /** ++ * The backlight color choosing algorithm was mostly ported to javascript from the ++ * Unity7 C++ source of Canonicals: ++ * https://bazaar.launchpad.net/~unity-team/unity/trunk/view/head:/launcher/LauncherIcon.cpp ++ * so it more or less works the same way. ++ */ ++ _getColorPalette: function() { ++ if (iconCacheMap.get(this._app.get_id())) { ++ // We already know the answer ++ return iconCacheMap.get(this._app.get_id()); ++ } ++ ++ let pixBuf = this._getIconPixBuf(); ++ if (pixBuf == null) ++ return null; ++ ++ let pixels = pixBuf.get_pixels(), ++ offset = 0; ++ ++ let total = 0, ++ rTotal = 0, ++ gTotal = 0, ++ bTotal = 0; ++ ++ let resample_y = 1, ++ resample_x = 1; ++ ++ // Resampling of large icons ++ // We resample icons larger than twice the desired size, as the resampling ++ // to a size s ++ // DOMINANT_COLOR_ICON_SIZE < s < 2*DOMINANT_COLOR_ICON_SIZE, ++ // most of the case exactly DOMINANT_COLOR_ICON_SIZE as the icon size is tipycally ++ // a multiple of it. ++ let width = pixBuf.get_width(); ++ let height = pixBuf.get_height(); ++ ++ // Resample ++ if (height >= 2* DOMINANT_COLOR_ICON_SIZE) ++ resample_y = Math.floor(height/DOMINANT_COLOR_ICON_SIZE); ++ ++ if (width >= 2* DOMINANT_COLOR_ICON_SIZE) ++ resample_x = Math.floor(width/DOMINANT_COLOR_ICON_SIZE); ++ ++ if (resample_x !==1 || resample_y !== 1) ++ pixels = this._resamplePixels(pixels, resample_x, resample_y); ++ ++ // computing the limit outside the for (where it would be repeated at each iteration) ++ // for performance reasons ++ let limit = pixels.length; ++ for (let offset = 0; offset < limit; offset+=4) { ++ let r = pixels[offset], ++ g = pixels[offset + 1], ++ b = pixels[offset + 2], ++ a = pixels[offset + 3]; ++ ++ let saturation = (Math.max(r,g, b) - Math.min(r,g, b)); ++ let relevance = 0.1 * 255 * 255 + 0.9 * a * saturation; ++ ++ rTotal += r * relevance; ++ gTotal += g * relevance; ++ bTotal += b * relevance; ++ ++ total += relevance; ++ } ++ ++ total = total * 255; ++ ++ let r = rTotal / total, ++ g = gTotal / total, ++ b = bTotal / total; ++ ++ let hsv = ColorUtils.RGBtoHSV(r * 255, g * 255, b * 255); ++ ++ if (hsv.s > 0.15) ++ hsv.s = 0.65; ++ hsv.v = 0.90; ++ ++ let rgb = ColorUtils.HSVtoRGB(hsv.h, hsv.s, hsv.v); ++ ++ // Cache the result. ++ let backgroundColor = { ++ lighter: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0.2), ++ original: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, 0), ++ darker: ColorUtils.colorLuminance(rgb.r, rgb.g, rgb.b, -0.5) ++ }; ++ ++ if (iconCacheMap.size >= MAX_CACHED_ITEMS) { ++ //delete oldest cached values (which are in order of insertions) ++ let ctr=0; ++ for (let key of iconCacheMap.keys()) { ++ if (++ctr > BATCH_SIZE_TO_DELETE) ++ break; ++ iconCacheMap.delete(key); ++ } ++ } ++ ++ iconCacheMap.set(this._app.get_id(), backgroundColor); ++ ++ return backgroundColor; ++ }, ++ ++ /** ++ * Downsample large icons before scanning for the backlight color to ++ * improve performance. ++ * ++ * @param pixBuf ++ * @param pixels ++ * @param resampleX ++ * @param resampleY ++ * ++ * @return []; ++ */ ++ _resamplePixels: function (pixels, resampleX, resampleY) { ++ let resampledPixels = []; ++ // computing the limit outside the for (where it would be repeated at each iteration) ++ // for performance reasons ++ let limit = pixels.length / (resampleX * resampleY) / 4; ++ for (let i = 0; i < limit; i++) { ++ let pixel = i * resampleX * resampleY; ++ ++ resampledPixels.push(pixels[pixel * 4]); ++ resampledPixels.push(pixels[pixel * 4 + 1]); ++ resampledPixels.push(pixels[pixel * 4 + 2]); ++ resampledPixels.push(pixels[pixel * 4 + 3]); ++ } ++ ++ return resampledPixels; ++ } ++ ++}); ++ ++var drawRoundedLine = function(cr, x, y, width, height, isRoundLeft, isRoundRight, stroke, fill) { ++ if (height > width) { ++ y += Math.floor((height - width) / 2.0); ++ height = width; ++ } ++ ++ height = 2.0 * Math.floor(height / 2.0); ++ ++ var leftRadius = isRoundLeft ? height / 2.0 : 0.0; ++ var rightRadius = isRoundRight ? height / 2.0 : 0.0; ++ ++ cr.moveTo(x + width - rightRadius, y); ++ cr.lineTo(x + leftRadius, y); ++ if (isRoundLeft) ++ cr.arcNegative(x + leftRadius, y + leftRadius, leftRadius, -Math.PI/2, Math.PI/2); ++ else ++ cr.lineTo(x, y + height); ++ cr.lineTo(x + width - rightRadius, y + height); ++ if (isRoundRight) ++ cr.arcNegative(x + width - rightRadius, y + rightRadius, rightRadius, Math.PI/2, -Math.PI/2); ++ else ++ cr.lineTo(x + width, y); ++ cr.closePath(); ++ ++ if (fill != null) { ++ cr.setSource(fill); ++ cr.fillPreserve(); ++ } ++ if (stroke != null) ++ cr.setSource(stroke); ++ cr.stroke(); ++} ++ ++/** ++ * Check if an app exists in the system. ++ */ ++var checkedCommandsMap = new Map(); ++ ++function checkIfCommandExists(app) { ++ let answer = checkedCommandsMap.get(app); ++ if (answer === undefined) { ++ // Command is a shell built in, use shell to call it. ++ // Quotes around app value are important. They let command operate ++ // on the whole value, instead of having shell interpret it. ++ let cmd = "sh -c 'command -v \"" + app + "\"'"; ++ try { ++ let out = GLib.spawn_command_line_sync(cmd); ++ // out contains 1: stdout, 2: stderr, 3: exit code ++ answer = out[3] == 0; ++ } catch (ex) { ++ answer = false; ++ } ++ ++ checkedCommandsMap.set(app, answer); ++ } ++ return answer; ++} +diff --git a/extensions/dash-to-panel/windowPreview.js b/extensions/dash-to-panel/windowPreview.js +new file mode 100644 +index 00000000..45d08a04 +--- /dev/null ++++ b/extensions/dash-to-panel/windowPreview.js +@@ -0,0 +1,1145 @@ ++/* ++ * This file is part of the Dash-To-Panel extension for Gnome 3 ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++const Clutter = imports.gi.Clutter; ++const Config = imports.misc.config; ++const GLib = imports.gi.GLib; ++const Gtk = imports.gi.Gtk; ++const Main = imports.ui.main; ++const Mainloop = imports.mainloop; ++const Meta = imports.gi.Meta; ++const PopupMenu = imports.ui.popupMenu; ++const Signals = imports.signals; ++const St = imports.gi.St; ++const WindowManager = imports.ui.windowManager; ++const Workspace = imports.ui.workspace; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Panel = Me.imports.panel; ++const Taskbar = Me.imports.taskbar; ++const Utils = Me.imports.utils; ++ ++//timeout intervals ++const ENSURE_VISIBLE_MS = 200; ++ ++//timeout names ++const T1 = 'openMenuTimeout'; ++const T2 = 'closeMenuTimeout'; ++const T3 = 'peekTimeout'; ++const T4 = 'ensureVisibleTimeout'; ++ ++const MAX_TRANSLATION = 40; ++const HEADER_HEIGHT = 38; ++const MAX_CLOSE_BUTTON_SIZE = 30; ++const MIN_DIMENSION = 100; ++const FOCUSED_COLOR_OFFSET = 24; ++const HEADER_COLOR_OFFSET = -12; ++const FADE_SIZE = 36; ++const PEEK_INDEX_PROP = '_dtpPeekInitialIndex'; ++ ++let headerHeight = 0; ++let alphaBg = 0; ++let isLeftButtons = false; ++let isTopHeader = true; ++let isManualStyling = false; ++let scaleFactor = 1; ++let animationTime = 0; ++let aspectRatio = {}; ++ ++var PreviewMenu = Utils.defineClass({ ++ Name: 'DashToPanel-PreviewMenu', ++ Extends: St.Widget, ++ Signals: { 'open-state-changed': {} }, ++ ++ _init: function(panel) { ++ this.callParent('_init', { layout_manager: new Clutter.BinLayout() }); ++ ++ let geom = panel.geom; ++ this.panel = panel; ++ this.currentAppIcon = null; ++ this._focusedPreview = null; ++ this._peekedWindow = null; ++ this.peekInitialWorkspaceIndex = -1; ++ this.opened = false; ++ this.isVertical = geom.position == St.Side.LEFT || geom.position == St.Side.RIGHT; ++ this._translationProp = 'translation_' + (this.isVertical ? 'x' : 'y'); ++ this._translationDirection = (geom.position == St.Side.TOP || geom.position == St.Side.LEFT ? -1 : 1); ++ this._translationOffset = Math.min(panel.dtpSize, MAX_TRANSLATION) * this._translationDirection; ++ ++ this.menu = new St.Widget({ ++ name: 'preview-menu', ++ layout_manager: new Clutter.BinLayout(), ++ reactive: true, ++ track_hover: true, ++ x_expand: true, ++ y_expand: true, ++ x_align: Clutter.ActorAlign[geom.position != St.Side.RIGHT ? 'START' : 'END'], ++ y_align: Clutter.ActorAlign[geom.position != St.Side.BOTTOM ? 'START' : 'END'] ++ }); ++ this._box = new St.BoxLayout({ vertical: this.isVertical }); ++ this._scrollView = new St.ScrollView({ ++ name: 'dashtopanelPreviewScrollview', ++ hscrollbar_policy: Gtk.PolicyType.NEVER, ++ vscrollbar_policy: Gtk.PolicyType.NEVER, ++ enable_mouse_scrolling: true, ++ y_expand: !this.isVertical ++ }); ++ ++ this._scrollView.add_actor(this._box); ++ this.menu.add_child(this._scrollView); ++ this.add_child(this.menu); ++ }, ++ ++ enable: function() { ++ this._timeoutsHandler = new Utils.TimeoutsHandler(); ++ this._signalsHandler = new Utils.GlobalSignalsHandler(); ++ ++ Main.layoutManager.addChrome(this, { affectsInputRegion: false }); ++ Main.layoutManager.trackChrome(this.menu, { affectsInputRegion: true }); ++ ++ this._resetHiddenState(); ++ this._refreshGlobals(); ++ this._updateClip(); ++ this.menu.set_position(1, 1); ++ ++ this._signalsHandler.add( ++ [ ++ this.menu, ++ 'notify::hover', ++ () => this._onHoverChanged() ++ ], ++ [ ++ this._scrollView, ++ 'scroll-event', ++ this._onScrollEvent.bind(this) ++ ], ++ [ ++ this.panel.panelBox, ++ 'style-changed', ++ () => this._updateClip() ++ ], ++ [ ++ Utils.DisplayWrapper.getScreen(), ++ 'in-fullscreen-changed', ++ () => { ++ if (global.display.focus_window && global.display.focus_window.is_fullscreen()) { ++ this.close(true); ++ } ++ } ++ ], ++ [ ++ Me.settings, ++ [ ++ 'changed::panel-sizes', ++ 'changed::window-preview-size', ++ 'changed::window-preview-padding', ++ 'changed::window-preview-show-title' ++ ], ++ () => { ++ this._refreshGlobals(); ++ this._updateClip(); ++ } ++ ] ++ ); ++ }, ++ ++ disable: function() { ++ this._timeoutsHandler.destroy(); ++ this._signalsHandler.destroy(); ++ ++ this.close(true); ++ ++ Main.layoutManager.untrackChrome(this.menu); ++ Main.layoutManager.removeChrome(this); ++ }, ++ ++ requestOpen: function(appIcon) { ++ let timeout = Me.settings.get_int('show-window-previews-timeout'); ++ ++ if (this.opened) { ++ timeout = Math.min(100, timeout); ++ } ++ ++ this._endOpenCloseTimeouts(); ++ this._timeoutsHandler.add([T1, timeout, () => this.open(appIcon)]); ++ }, ++ ++ requestClose: function() { ++ this._endOpenCloseTimeouts(); ++ this._addCloseTimeout(); ++ }, ++ ++ open: function(appIcon) { ++ if (this.currentAppIcon != appIcon) { ++ this.currentAppIcon = appIcon; ++ ++ if (!this.opened) { ++ this._refreshGlobals(); ++ ++ this.set_height(this.clipHeight); ++ this.menu.show(); ++ ++ setStyle(this.menu, 'background: ' + Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, alphaBg)); ++ } ++ ++ this._mergeWindows(appIcon); ++ this._updatePosition(); ++ this._animateOpenOrClose(true); ++ ++ this._setReactive(true); ++ this._setOpenedState(true); ++ } ++ }, ++ ++ close: function(immediate) { ++ this._endOpenCloseTimeouts(); ++ this._removeFocus(); ++ this._endPeek(); ++ ++ if (immediate) { ++ Utils.stopAnimations(this.menu); ++ this._resetHiddenState(); ++ } else { ++ this._animateOpenOrClose(false, () => this._resetHiddenState()); ++ } ++ ++ this._setReactive(false); ++ this.currentAppIcon = null; ++ }, ++ ++ update: function(appIcon, windows) { ++ if (this.currentAppIcon == appIcon) { ++ if (windows && !windows.length) { ++ this.close(); ++ } else { ++ this._addAndRemoveWindows(windows); ++ this._updatePosition(); ++ } ++ } ++ }, ++ ++ updatePosition: function() { ++ this._updatePosition(); ++ }, ++ ++ focusNext: function() { ++ let previews = this._box.get_children(); ++ let currentIndex = this._focusedPreview ? previews.indexOf(this._focusedPreview) : -1; ++ let nextIndex = currentIndex + 1; ++ ++ nextIndex = previews[nextIndex] ? nextIndex : 0; ++ ++ if (previews[nextIndex]) { ++ this._removeFocus(); ++ previews[nextIndex].setFocus(true); ++ this._focusedPreview = previews[nextIndex]; ++ } ++ ++ return nextIndex; ++ }, ++ ++ activateFocused: function() { ++ if (this.opened && this._focusedPreview) { ++ this._focusedPreview.activate(); ++ } ++ }, ++ ++ requestPeek: function(window) { ++ this._timeoutsHandler.remove(T3); ++ ++ if (Me.settings.get_boolean('peek-mode')) { ++ if (this.peekInitialWorkspaceIndex < 0) { ++ this._timeoutsHandler.add([T3, Me.settings.get_int('enter-peek-mode-timeout'), () => this._peek(window)]); ++ } else { ++ this._peek(window); ++ } ++ } ++ }, ++ ++ endPeekHere: function() { ++ this._endPeek(true); ++ }, ++ ++ ensureVisible: function(preview) { ++ let [ , upper, pageSize] = this._getScrollAdjustmentValues(); ++ ++ if (upper > pageSize) { ++ this._timeoutsHandler.add([ ++ T4, ++ ENSURE_VISIBLE_MS, ++ () => Utils.ensureActorVisibleInScrollView(this._scrollView, preview, MIN_DIMENSION, () => this._updateScrollFade()) ++ ]); ++ } ++ }, ++ ++ getCurrentAppIcon: function() { ++ return this.currentAppIcon; ++ }, ++ ++ _setReactive: function(reactive) {  ++ this._box.get_children().forEach(c => c.reactive = reactive); ++ this.menu.reactive = reactive; ++ }, ++ ++ _setOpenedState: function(opened) { ++ this.opened = opened; ++ this.emit('open-state-changed'); ++ }, ++ ++ _resetHiddenState: function() { ++ this.menu.hide(); ++ this.set_height(0); ++ this._setOpenedState(false); ++ this.menu.opacity = 0; ++ this.menu[this._translationProp] = this._translationOffset; ++ this._box.get_children().forEach(c => c.destroy()); ++ }, ++ ++ _removeFocus: function() { ++ if (this._focusedPreview) { ++ this._focusedPreview.setFocus(false); ++ this._focusedPreview = null; ++ } ++ }, ++ ++ _mergeWindows: function(appIcon, windows) { ++ windows = windows || (appIcon.window ? [appIcon.window] : appIcon.getAppIconInterestingWindows()); ++ windows.sort(Taskbar.sortWindowsCompareFunction); ++ ++ let currentPreviews = this._box.get_children(); ++ let l = Math.max(windows.length, currentPreviews.length); ++ ++ for (let i = 0; i < l; ++i) { ++ if (currentPreviews[i] && windows[i]) { ++ currentPreviews[i].assignWindow(windows[i], this.opened); ++ } else if (!currentPreviews[i]) { ++ this._addNewPreview(windows[i]); ++ } else if (!windows[i]) { ++ currentPreviews[i][!this.opened ? 'destroy' : 'animateOut'](); ++ } ++ } ++ }, ++ ++ _addAndRemoveWindows: function(windows) { ++ let currentPreviews = this._box.get_children(); ++ ++ windows.sort(Taskbar.sortWindowsCompareFunction); ++ ++ for (let i = 0, l = windows.length; i < l; ++i) { ++ let currentIndex = Utils.findIndex(currentPreviews, c => c.window == windows[i]); ++ ++ if (currentIndex < 0) { ++ this._addNewPreview(windows[i]); ++ } else { ++ currentPreviews[currentIndex].assignWindow(windows[i]); ++ currentPreviews.splice(currentIndex, 1); ++ ++ if (this._peekedWindow && this._peekedWindow == windows[i]) { ++ this.requestPeek(windows[i]); ++ } ++ } ++ } ++ ++ currentPreviews.forEach(c => c.animateOut()); ++ }, ++ ++ _addNewPreview: function(window) { ++ let preview = new Preview(this); ++ ++ this._box.add_child(preview); ++ preview.adjustOnStage(); ++ preview.assignWindow(window, this.opened); ++ }, ++ ++ _addCloseTimeout: function() { ++ this._timeoutsHandler.add([T2, Me.settings.get_int('leave-timeout'), () => this.close()]); ++ }, ++ ++ _onHoverChanged: function() { ++ this._endOpenCloseTimeouts(); ++ ++ if (this.currentAppIcon && !this.menu.hover) { ++ this._addCloseTimeout(); ++ this._endPeek(); ++ } ++ }, ++ ++ _onScrollEvent: function(actor, event) { ++ if (!event.is_pointer_emulated()) { ++ let vOrh = this.isVertical ? 'v' : 'h'; ++ let adjustment = this._scrollView['get_' + vOrh + 'scroll_bar']().get_adjustment(); ++ let increment = adjustment.step_increment; ++ let delta = increment; ++ ++ switch (event.get_scroll_direction()) { ++ case Clutter.ScrollDirection.UP: ++ delta = -increment; ++ break; ++ case Clutter.ScrollDirection.SMOOTH: ++ let [dx, dy] = event.get_scroll_delta(); ++ delta = dy * increment; ++ delta += dx * increment; ++ break; ++ } ++ ++ adjustment.set_value(adjustment.get_value() + delta); ++ this._updateScrollFade(); ++ } ++ ++ return Clutter.EVENT_STOP; ++ }, ++ ++ _endOpenCloseTimeouts: function() { ++ this._timeoutsHandler.remove(T1); ++ this._timeoutsHandler.remove(T2); ++ this._timeoutsHandler.remove(T4); ++ }, ++ ++ _refreshGlobals: function() { ++ isLeftButtons = Meta.prefs_get_button_layout().left_buttons.indexOf(Meta.ButtonFunction.CLOSE) >= 0; ++ isTopHeader = Me.settings.get_string('window-preview-title-position') == 'TOP'; ++ isManualStyling = Me.settings.get_boolean('window-preview-manual-styling'); ++ scaleFactor = Utils.getScaleFactor(); ++ headerHeight = Me.settings.get_boolean('window-preview-show-title') ? HEADER_HEIGHT * scaleFactor : 0; ++ animationTime = Me.settings.get_int('window-preview-animation-time') * .001; ++ aspectRatio.x = { ++ size: Me.settings.get_int('window-preview-aspect-ratio-x'), ++ fixed: Me.settings.get_boolean('window-preview-fixed-x') ++ }; ++ aspectRatio.y = { ++ size: Me.settings.get_int('window-preview-aspect-ratio-y'), ++ fixed: Me.settings.get_boolean('window-preview-fixed-y') ++ }; ++ ++ alphaBg = Me.settings.get_boolean('preview-use-custom-opacity') ? ++ Me.settings.get_int('preview-custom-opacity') * .01 : ++ this.panel.dynamicTransparency.alpha; ++ }, ++ ++ _updateClip: function() { ++ let x, y, w; ++ let geom = this.panel.getGeometry(); ++ let panelBoxTheme = this.panel.panelBox.get_theme_node(); ++ let previewSize = (Me.settings.get_int('window-preview-size') + ++ Me.settings.get_int('window-preview-padding') * 2) * scaleFactor; ++ ++ if (this.isVertical) { ++ w = previewSize; ++ this.clipHeight = this.panel.monitor.height; ++ y = this.panel.monitor.y; ++ } else { ++ w = this.panel.monitor.width; ++ this.clipHeight = (previewSize + headerHeight); ++ x = this.panel.monitor.x; ++ } ++ ++ if (geom.position == St.Side.LEFT) { ++ x = this.panel.monitor.x + this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.LEFT); ++ } else if (geom.position == St.Side.RIGHT) { ++ x = this.panel.monitor.x + this.panel.monitor.width - (this.panel.dtpSize + previewSize) - panelBoxTheme.get_padding(St.Side.RIGHT); ++ } else if (geom.position == St.Side.TOP) { ++ y = this.panel.monitor.y + this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.TOP); ++ } else { //St.Side.BOTTOM ++ y = this.panel.monitor.y + this.panel.monitor.height - (this.panel.dtpSize + panelBoxTheme.get_padding(St.Side.BOTTOM) + previewSize + headerHeight); ++ } ++ ++ Utils.setClip(this, x, y, w, this.clipHeight); ++ }, ++ ++ _updatePosition: function() { ++ let sourceNode = this.currentAppIcon.actor.get_theme_node(); ++ let sourceContentBox = sourceNode.get_content_box(this.currentAppIcon.actor.get_allocation_box()); ++ let sourceAllocation = Utils.getTransformedAllocation(this.currentAppIcon.actor); ++ let [previewsWidth, previewsHeight] = this._getPreviewsSize(); ++ let appIconMargin = Me.settings.get_int('appicon-margin') / scaleFactor; ++ let x = 0, y = 0; ++ ++ previewsWidth = Math.min(previewsWidth, this.panel.monitor.width); ++ previewsHeight = Math.min(previewsHeight, this.panel.monitor.height); ++ this._updateScrollFade(previewsWidth < this.panel.monitor.width && previewsHeight < this.panel.monitor.height); ++ ++ if (this.isVertical) { ++ y = sourceAllocation.y1 + appIconMargin - this.panel.monitor.y + (sourceContentBox.y2 - sourceContentBox.y1 - previewsHeight) * .5; ++ y = Math.max(y, 0); ++ y = Math.min(y, this.panel.monitor.height - previewsHeight); ++ } else { ++ x = sourceAllocation.x1 + appIconMargin - this.panel.monitor.x + (sourceContentBox.x2 - sourceContentBox.x1 - previewsWidth) * .5; ++ x = Math.max(x, 0); ++ x = Math.min(x, this.panel.monitor.width - previewsWidth); ++ } ++ ++ if (!this.opened) { ++ this.menu.set_position(x, y); ++ this.menu.set_size(previewsWidth, previewsHeight); ++ } else { ++ Utils.animate(this.menu, getTweenOpts({ x: x, y: y, width: previewsWidth, height: previewsHeight })); ++ } ++ }, ++ ++ _updateScrollFade: function(remove) { ++ let [value, upper, pageSize] = this._getScrollAdjustmentValues(); ++ let needsFade = Math.round(upper) > Math.round(pageSize); ++ let fadeWidgets = this.menu.get_children().filter(c => c != this._scrollView); ++ ++ if (!remove && needsFade) { ++ if (!fadeWidgets.length) { ++ fadeWidgets.push(this._getFadeWidget()); ++ fadeWidgets.push(this._getFadeWidget(true)); ++ ++ this.menu.add_child(fadeWidgets[0]); ++ this.menu.add_child(fadeWidgets[1]); ++ } ++ ++ fadeWidgets[0].visible = value > 0; ++ fadeWidgets[1].visible = value + pageSize < upper; ++ } else if (remove || (!needsFade && fadeWidgets.length)) { ++ fadeWidgets.forEach(fw => fw.destroy()); ++ } ++ }, ++ ++ _getScrollAdjustmentValues: function() { ++ let [value , , upper, , , pageSize] = this._scrollView[(this.isVertical ? 'v' : 'h') + 'scroll'].adjustment.get_values(); ++ ++ return [value, upper, pageSize]; ++ }, ++ ++ _getFadeWidget: function(end) { ++ let x = 0, y = 0; ++ let startBg = Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, Math.min(alphaBg + .1, 1)); ++ let endBg = Utils.getrgbaColor(this.panel.dynamicTransparency.backgroundColorRgb, 0) ++ let fadeStyle = 'background-gradient-start:' + startBg + ++ 'background-gradient-end:' + endBg + ++ 'background-gradient-direction:' + this.panel.getOrientation(); ++ ++ if (this.isVertical) { ++ y = end ? this.panel.monitor.height - FADE_SIZE : 0; ++ } else { ++ x = end ? this.panel.monitor.width - FADE_SIZE : 0; ++ } ++ ++ let fadeWidget = new St.Widget({ ++ reactive: false, ++ pivot_point: Utils.getPoint({ x: .5, y: .5 }), ++ rotation_angle_z: end ? 180 : 0, ++ style: fadeStyle, ++ x: x, y: y, ++ width: this.isVertical ? this.width : FADE_SIZE, ++ height: this.isVertical ? FADE_SIZE : this.height ++ }); ++ ++ return fadeWidget; ++ }, ++ ++ _getPreviewsSize: function() { ++ let previewsWidth = 0; ++ let previewsHeight = 0; ++ ++ this._box.get_children().forEach(c => { ++ if (!c.animatingOut) { ++ let [width, height] = c.getSize(); ++ ++ if (this.isVertical) { ++ previewsWidth = Math.max(width, previewsWidth); ++ previewsHeight += height; ++ } else { ++ previewsWidth += width; ++ previewsHeight = Math.max(height, previewsHeight); ++ } ++ } ++ }); ++ ++ return [previewsWidth, previewsHeight]; ++ }, ++ ++ _animateOpenOrClose: function(show, onComplete) { ++ let isTranslationAnimation = this.menu[this._translationProp] != 0; ++ let tweenOpts = { ++ opacity: show ? 255 : 0, ++ transition: show ? 'easeInOutQuad' : 'easeInCubic', ++ onComplete: () => { ++ if (isTranslationAnimation) { ++ Main.layoutManager._queueUpdateRegions(); ++ } ++ ++ (onComplete || (() => {}))(); ++ } ++ }; ++ ++ tweenOpts[this._translationProp] = show ? this._translationDirection : this._translationOffset; ++ ++ Utils.animate(this.menu, getTweenOpts(tweenOpts)); ++ }, ++ ++ _peek: function(window) { ++ let currentWorkspace = Utils.getCurrentWorkspace(); ++ let windowWorkspace = window.get_workspace(); ++ let focusWindow = () => this._focusMetaWindow(Me.settings.get_int('peek-mode-opacity'), window); ++ ++ this._restorePeekedWindowStack(); ++ this._peekedWindow = window; ++ ++ if (currentWorkspace != windowWorkspace) { ++ this._switchToWorkspaceImmediate(windowWorkspace.index()); ++ this._timeoutsHandler.add([T3, 100, focusWindow]); ++ } else { ++ focusWindow(); ++ } ++ ++ if (this.peekInitialWorkspaceIndex < 0) { ++ this.peekInitialWorkspaceIndex = currentWorkspace.index(); ++ } ++ }, ++ ++ _endPeek: function(stayHere) { ++ this._timeoutsHandler.remove(T3); ++ ++ if (this._peekedWindow) { ++ let immediate = !stayHere && this.peekInitialWorkspaceIndex != Utils.getCurrentWorkspace().index(); ++ ++ this._restorePeekedWindowStack(); ++ this._focusMetaWindow(255, this._peekedWindow, immediate, true); ++ this._peekedWindow = null; ++ ++ if (!stayHere) { ++ this._switchToWorkspaceImmediate(this.peekInitialWorkspaceIndex); ++ } ++ ++ this.peekInitialWorkspaceIndex = -1; ++ } ++ }, ++ ++ _switchToWorkspaceImmediate: function(workspaceIndex) { ++ let workspace = Utils.getWorkspaceByIndex(workspaceIndex); ++ let shouldAnimate = Main.wm._shouldAnimate; ++ ++ if (!workspace || (!workspace.list_windows().length && ++ workspaceIndex < Utils.getWorkspaceCount() - 1)) { ++ workspace = Utils.getCurrentWorkspace(); ++ } ++ ++ Main.wm._shouldAnimate = () => false; ++ workspace.activate(global.display.get_current_time_roundtrip()); ++ Main.wm._shouldAnimate = shouldAnimate; ++ }, ++ ++ _focusMetaWindow: function(dimOpacity, window, immediate, ignoreFocus) { ++ window.get_workspace().list_windows().forEach(mw => { ++ let wa = mw.get_compositor_private(); ++ let isFocused = !ignoreFocus && mw == window; ++ ++ if (wa) { ++ if (isFocused) { ++ mw[PEEK_INDEX_PROP] = wa.get_parent().get_children().indexOf(wa); ++ wa.get_parent().set_child_above_sibling(wa, null); ++ } ++ ++ if (isFocused && mw.minimized) { ++ wa.show(); ++ } ++ ++ if (!mw.minimized) { ++ let tweenOpts = getTweenOpts({ opacity: isFocused ? 255 : dimOpacity }); ++ ++ if (immediate && !mw.is_on_all_workspaces()) { ++ tweenOpts.time = 0; ++ } ++ ++ Utils.animateWindowOpacity(wa, tweenOpts); ++ } ++ } ++ }); ++ }, ++ ++ _restorePeekedWindowStack: function() { ++ let windowActor = this._peekedWindow ? this._peekedWindow.get_compositor_private() : null; ++ ++ if (windowActor) { ++ if (this._peekedWindow.hasOwnProperty(PEEK_INDEX_PROP)) { ++ windowActor.get_parent().set_child_at_index(windowActor, this._peekedWindow[PEEK_INDEX_PROP]); ++ delete this._peekedWindow[PEEK_INDEX_PROP]; ++ } ++ ++ if (this._peekedWindow.minimized) { ++ windowActor.hide(); ++ } ++ } ++ }, ++}); ++ ++var Preview = Utils.defineClass({ ++ Name: 'DashToPanel-Preview', ++ Extends: St.Widget, ++ ++ _init: function(previewMenu) { ++ this.callParent('_init', { ++ style_class: 'preview-container', ++ reactive: true, ++ track_hover: true, ++ layout_manager: new Clutter.BinLayout() ++ }); ++ ++ this.window = null; ++ this._waitWindowId = 0; ++ this._needsCloseButton = true; ++ this.cloneWidth = this.cloneHeight = 0; ++ this._previewMenu = previewMenu; ++ this._padding = Me.settings.get_int('window-preview-padding') * scaleFactor; ++ this._previewDimensions = this._getPreviewDimensions(); ++ this.animatingOut = false; ++ ++ let box = new St.Widget({ layout_manager: new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL }), y_expand: true }); ++ let [previewBinWidth, previewBinHeight] = this._getBinSize(); ++ let closeButton = new St.Button({ style_class: 'window-close', accessible_name: 'Close window' }); ++ ++ if (Config.PACKAGE_VERSION >= '3.31.9') { ++ closeButton.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' })); ++ } ++ ++ this._closeButtonBin = new St.Widget({ ++ style_class: 'preview-close-btn-container', ++ layout_manager: new Clutter.BinLayout(), ++ opacity: 0, ++ x_expand: true, y_expand: true, ++ x_align: Clutter.ActorAlign[isLeftButtons ? 'START' : 'END'], ++ y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END'] ++ }); ++ ++ this._closeButtonBin.add_child(closeButton); ++ ++ this._previewBin = new St.Widget({ ++ layout_manager: new Clutter.BinLayout(), ++ x_expand: true, y_expand: true, ++ style: 'padding: ' + this._padding / scaleFactor + 'px;' ++ }); ++ ++ this._previewBin.set_size(previewBinWidth, previewBinHeight); ++ ++ box.add_child(this._previewBin); ++ ++ if (headerHeight) { ++ let headerBox = new St.Widget({ ++ style_class: 'preview-header-box', ++ layout_manager: new Clutter.BoxLayout(), ++ x_expand: true, ++ y_align: Clutter.ActorAlign[isTopHeader ? 'START' : 'END'] ++ }); ++ ++ setStyle(headerBox, this._getBackgroundColor(HEADER_COLOR_OFFSET, 1)); ++ this._workspaceIndicator = new St.Label({ y_align: Clutter.ActorAlign.CENTER }); ++ this._windowTitle = new St.Label({ y_align: Clutter.ActorAlign.CENTER, x_expand: true }); ++ ++ this._iconBin = new St.Widget({ layout_manager: new Clutter.BinLayout() }); ++ this._iconBin.set_size(headerHeight, headerHeight); ++ ++ headerBox.add_child(this._iconBin); ++ headerBox.insert_child_at_index(this._workspaceIndicator, isLeftButtons ? 0 : 1); ++ headerBox.insert_child_at_index(this._windowTitle, isLeftButtons ? 1 : 2); ++ ++ box.insert_child_at_index(headerBox, isTopHeader ? 0 : 1); ++ } ++ ++ this.add_child(box); ++ this.add_child(this._closeButtonBin); ++ ++ closeButton.connect('clicked', () => this._onCloseBtnClick()); ++ this.connect('notify::hover', () => this._onHoverChanged()); ++ this.connect('button-release-event', (actor, e) => this._onButtonReleaseEvent(e)); ++ this.connect('destroy', () => this._onDestroy()); ++ }, ++ ++ adjustOnStage: function() { ++ let closeButton = this._closeButtonBin.get_first_child(); ++ let closeButtonHeight = closeButton.height; ++ let maxCloseButtonSize = MAX_CLOSE_BUTTON_SIZE * scaleFactor; ++ let closeButtonBorderRadius = ''; ++ ++ if (closeButtonHeight > maxCloseButtonSize) { ++ closeButtonHeight = maxCloseButtonSize; ++ closeButton.set_size(closeButtonHeight, closeButtonHeight); ++ } ++ ++ if (!headerHeight) { ++ closeButtonBorderRadius = 'border-radius: '; ++ ++ if (isTopHeader) { ++ closeButtonBorderRadius += (isLeftButtons ? '0 0 4px 0;' : '0 0 0 4px;'); ++ } else { ++ closeButtonBorderRadius += (isLeftButtons ? '0 4px 0 0;' : '4px 0 0 0;'); ++ } ++ } ++ ++ setStyle( ++ this._closeButtonBin, ++ 'padding: ' + (headerHeight ? Math.round((headerHeight - closeButtonHeight) * .5 / scaleFactor) : 4) + 'px;' + ++ this._getBackgroundColor(HEADER_COLOR_OFFSET, headerHeight ? 1 : .6) + ++ closeButtonBorderRadius ++ ); ++ }, ++ ++ assignWindow: function(window, animateSize) { ++ if (this.window != window) { ++ let _assignWindowClone = () => { ++ if (window.get_compositor_private()) { ++ let cloneBin = this._getWindowCloneBin(window); ++ ++ this._resizeClone(cloneBin, window); ++ this._addClone(cloneBin, animateSize); ++ this._previewMenu.updatePosition(); ++ } else if (!this._waitWindowId) { ++ this._waitWindowId = Mainloop.idle_add(() => { ++ this._waitWindowId = 0; ++ ++ if (this._previewMenu.opened) { ++ _assignWindowClone(); ++ } ++ }); ++ } ++ }; ++ ++ _assignWindowClone(); ++ } ++ ++ this._cancelAnimateOut(); ++ this._removeWindowSignals(); ++ this.window = window; ++ this._needsCloseButton = window.can_close() && !Utils.checkIfWindowHasTransient(window); ++ this._updateHeader(); ++ }, ++ ++ animateOut: function() { ++ if (!this.animatingOut) { ++ let tweenOpts = getTweenOpts({ opacity: 0, width: 0, height: 0, onComplete: () => this.destroy() }); ++ ++ this.animatingOut = true; ++ ++ Utils.stopAnimations(this); ++ Utils.animate(this, tweenOpts); ++ } ++ }, ++ ++ getSize: function() { ++ let [binWidth, binHeight] = this._getBinSize(); ++ ++ binWidth = Math.max(binWidth, this.cloneWidth + this._padding * 2); ++ binHeight = Math.max(binHeight, this.cloneHeight + this._padding * 2) + headerHeight; ++ ++ return [binWidth, binHeight]; ++ }, ++ ++ setFocus: function(focused) { ++ this._hideOrShowCloseButton(!focused); ++ setStyle(this, this._getBackgroundColor(FOCUSED_COLOR_OFFSET, focused ? '-' : 0)); ++ ++ if (focused) { ++ this._previewMenu.ensureVisible(this); ++ this._previewMenu.requestPeek(this.window); ++ } ++ }, ++ ++ activate: function() { ++ this._previewMenu.endPeekHere(); ++ this._previewMenu.close(); ++ Main.activateWindow(this.window); ++ }, ++ ++ _onDestroy: function() { ++ if (this._waitWindowId) { ++ GLib.source_remove(this._waitWindowId); ++ this._waitWindowId = 0; ++ } ++ ++ this._removeWindowSignals(); ++ }, ++ ++ _onHoverChanged: function() { ++ this.setFocus(this.hover); ++ }, ++ ++ _onCloseBtnClick: function() { ++ this._hideOrShowCloseButton(true); ++ this.reactive = false; ++ ++ if (!Me.settings.get_boolean('group-apps')) { ++ this._previewMenu.close(); ++ } else { ++ this._previewMenu.endPeekHere(); ++ } ++ ++ this.window.delete(global.get_current_time()); ++ }, ++ ++ _onButtonReleaseEvent: function(e) { ++ switch (e.get_button()) { ++ case 1: // Left click ++ this.activate(); ++ break; ++ case 2: // Middle click ++ if (Me.settings.get_boolean('preview-middle-click-close')) { ++ this._onCloseBtnClick(); ++ } ++ break; ++ case 3: // Right click ++ this._showContextMenu(e); ++ break; ++ } ++ ++ return Clutter.EVENT_STOP; ++ }, ++ ++ _cancelAnimateOut: function() { ++ if (this.animatingOut) { ++ this.animatingOut = false; ++ ++ Utils.stopAnimations(this); ++ Utils.animate(this, getTweenOpts({ opacity: 255, width: this.cloneWidth, height: this.cloneHeight })); ++ } ++ }, ++ ++ _showContextMenu: function(e) { ++ let coords = e.get_coords(); ++ let currentWorkspace = this._previewMenu.peekInitialWorkspaceIndex < 0 ? ++ Utils.getCurrentWorkspace() : ++ Utils.getWorkspaceByIndex(this._previewMenu.peekInitialWorkspaceIndex); ++ ++ Main.wm._showWindowMenu(null, this.window, Meta.WindowMenuType.WM, { ++ x: coords[0], ++ y: coords[1], ++ width: 0, ++ height: 0 ++ }); ++ ++ let ctxMenuData = Main.wm._windowMenuManager._manager._menus[0]; ++ ++ ctxMenuData.menu.connect('open-state-changed', () => this._previewMenu.menu.sync_hover()); ++ ++ if (this.window.get_workspace() != currentWorkspace) { ++ let menuItem = new PopupMenu.PopupMenuItem(_('Move to current Workspace') + ' [' + (currentWorkspace.index() + 1) + ']'); ++ let menuItems = ctxMenuData.menu.box.get_children(); ++ let insertIndex = Utils.findIndex(menuItems, c => c._delegate instanceof PopupMenu.PopupSeparatorMenuItem); ++ ++ insertIndex = insertIndex >= 0 ? insertIndex : menuItems.length - 1; ++ ctxMenuData.menu.addMenuItem(menuItem, insertIndex); ++ menuItem.connect('activate', () => this.window.change_workspace(currentWorkspace)); ++ } ++ }, ++ ++ _removeWindowSignals: function() { ++ if (this._titleWindowChangeId) { ++ this.window.disconnect(this._titleWindowChangeId); ++ this._titleWindowChangeId = 0; ++ } ++ }, ++ ++ _updateHeader: function() { ++ if (headerHeight) { ++ let iconTextureSize = Me.settings.get_boolean('window-preview-use-custom-icon-size') ? ++ Me.settings.get_int('window-preview-custom-icon-size') : ++ headerHeight / scaleFactor * .6; ++ let icon = this._previewMenu.getCurrentAppIcon().app.create_icon_texture(iconTextureSize); ++ let workspaceIndex = ''; ++ let workspaceStyle = null; ++ let fontScale = Me.desktopSettings.get_double('text-scaling-factor'); ++ let commonTitleStyles = 'color: ' + Me.settings.get_string('window-preview-title-font-color') + ';' + ++ 'font-size: ' + Me.settings.get_int('window-preview-title-font-size') * fontScale + 'px;' + ++ 'font-weight: ' + Me.settings.get_string('window-preview-title-font-weight') + ';'; ++ ++ this._iconBin.destroy_all_children(); ++ this._iconBin.add_child(icon); ++ ++ if (!Me.settings.get_boolean('isolate-workspaces')) { ++ workspaceIndex = (this.window.get_workspace().index() + 1).toString(); ++ workspaceStyle = 'margin: 0 4px 0 ' + (isLeftButtons ? Math.round((headerHeight - icon.width) * .5) + 'px' : '0') + '; padding: 0 4px;' + ++ 'border: 2px solid ' + this._getRgbaColor(FOCUSED_COLOR_OFFSET, .8) + 'border-radius: 2px;' + commonTitleStyles; ++ } ++ ++ this._workspaceIndicator.text = workspaceIndex; ++ setStyle(this._workspaceIndicator, workspaceStyle); ++ ++ this._titleWindowChangeId = this.window.connect('notify::title', () => this._updateWindowTitle()); ++ setStyle(this._windowTitle, 'max-width: 0px; padding-right: 4px;' + commonTitleStyles); ++ this._updateWindowTitle(); ++ } ++ }, ++ ++ _updateWindowTitle: function() { ++ this._windowTitle.text = this.window.title; ++ }, ++ ++ _hideOrShowCloseButton: function(hide) { ++ if (this._needsCloseButton) { ++ Utils.animate(this._closeButtonBin, getTweenOpts({ opacity: hide ? 0 : 255 })); ++ } ++ }, ++ ++ _getBackgroundColor: function(offset, alpha) { ++ return 'background-color: ' + this._getRgbaColor(offset, alpha) + ++ 'transition-duration:' + this._previewMenu.panel.dynamicTransparency.animationDuration; ++ }, ++ ++ _getRgbaColor: function(offset, alpha) { ++ alpha = Math.abs(alpha); ++ ++ if (isNaN(alpha)) { ++ alpha = alphaBg; ++ } ++ ++ return Utils.getrgbaColor(this._previewMenu.panel.dynamicTransparency.backgroundColorRgb, alpha, offset); ++ }, ++ ++ _addClone: function(newCloneBin, animateSize) { ++ let currentClones = this._previewBin.get_children(); ++ let newCloneOpts = getTweenOpts({ opacity: 255 }); ++ ++ this._previewBin.add_child(newCloneBin); ++ ++ if (currentClones.length) { ++ let currentCloneBin = currentClones.pop(); ++ let currentCloneOpts = getTweenOpts({ opacity: 0, onComplete: () => currentCloneBin.destroy() }); ++ ++ if (newCloneBin.width > currentCloneBin.width) { ++ newCloneOpts.width = newCloneBin.width; ++ newCloneBin.width = currentCloneBin.width; ++ } else { ++ currentCloneOpts.width = newCloneBin.width; ++ } ++ ++ if (newCloneBin.height > currentCloneBin.height) { ++ newCloneOpts.height = newCloneBin.height; ++ newCloneBin.height = currentCloneBin.height; ++ } else { ++ currentCloneOpts.height = newCloneBin.height; ++ } ++ ++ currentClones.forEach(c => c.destroy()); ++ Utils.animate(currentCloneBin, currentCloneOpts); ++ } else if (animateSize) { ++ newCloneBin.width = 0; ++ newCloneBin.height = 0; ++ newCloneOpts.width = this.cloneWidth; ++ newCloneOpts.height = this.cloneHeight; ++ } ++ ++ Utils.animate(newCloneBin, newCloneOpts); ++ }, ++ ++ _getWindowCloneBin: function(window) { ++ let frameRect = window.get_frame_rect(); ++ let bufferRect = window.get_buffer_rect(); ++ let clone = new Clutter.Clone({ source: window.get_compositor_private() }); ++ let cloneBin = new St.Widget({ ++ opacity: 0, ++ layout_manager: frameRect.width != bufferRect.width || ++ frameRect.height != bufferRect.height ? ++ new WindowCloneLayout(frameRect, bufferRect) : ++ new Clutter.BinLayout() ++ }); ++ ++ cloneBin.add_child(clone); ++ ++ return cloneBin; ++ }, ++ ++ _getBinSize: function() { ++ let [fixedWidth, fixedHeight] = this._previewDimensions; ++ ++ return [ ++ aspectRatio.x.fixed ? fixedWidth + this._padding * 2 : -1, ++ aspectRatio.y.fixed ? fixedHeight + this._padding * 2 : -1 ++ ]; ++ }, ++ ++ _resizeClone: function(cloneBin, window) { ++ let frameRect = cloneBin.layout_manager.frameRect || window.get_frame_rect(); ++ let [fixedWidth, fixedHeight] = this._previewDimensions; ++ let ratio = Math.min(fixedWidth / frameRect.width, fixedHeight / frameRect.height, 1); ++ let cloneWidth = frameRect.width * ratio; ++ let cloneHeight = frameRect.height * ratio; ++ ++ let clonePaddingTB = cloneHeight < MIN_DIMENSION ? MIN_DIMENSION - cloneHeight : 0; ++ let clonePaddingLR = cloneWidth < MIN_DIMENSION ? MIN_DIMENSION - cloneWidth : 0; ++ let clonePaddingTop = clonePaddingTB * .5; ++ let clonePaddingLeft = clonePaddingLR * .5; ++ ++ this.cloneWidth = cloneWidth + clonePaddingLR * scaleFactor; ++ this.cloneHeight = cloneHeight + clonePaddingTB * scaleFactor; ++ ++ cloneBin.set_style('padding: ' + clonePaddingTop + 'px ' + clonePaddingLeft + 'px;'); ++ cloneBin.layout_manager.ratio = ratio; ++ cloneBin.layout_manager.padding = [clonePaddingLeft * scaleFactor, clonePaddingTop * scaleFactor]; ++ ++ cloneBin.get_first_child().set_size(cloneWidth, cloneHeight); ++ }, ++ ++ _getPreviewDimensions: function() { ++ let size = Me.settings.get_int('window-preview-size') * scaleFactor; ++ let w, h; ++ ++ if (this._previewMenu.isVertical) { ++ w = size; ++ h = w * aspectRatio.y.size / aspectRatio.x.size; ++ } else { ++ h = size; ++ w = h * aspectRatio.x.size / aspectRatio.y.size; ++ } ++ ++ return [w, h]; ++ } ++}); ++ ++var WindowCloneLayout = Utils.defineClass({ ++ Name: 'DashToPanel-WindowCloneLayout', ++ Extends: Clutter.BinLayout, ++ ++ _init: function(frameRect, bufferRect) { ++ this.callParent('_init'); ++ ++ //the buffer_rect contains the transparent padding that must be removed ++ this.frameRect = frameRect; ++ this.bufferRect = bufferRect; ++ }, ++ ++ vfunc_allocate: function(actor, box, flags) { ++ let [width, height] = box.get_size(); ++ ++ box.set_origin( ++ (this.bufferRect.x - this.frameRect.x) * this.ratio + this.padding[0], ++ (this.bufferRect.y - this.frameRect.y) * this.ratio + this.padding[1] ++ ); ++ ++ box.set_size( ++ width + (this.bufferRect.width - this.frameRect.width) * this.ratio, ++ height + (this.bufferRect.height - this.frameRect.height) * this.ratio ++ ); ++ ++ Utils.allocate(actor.get_first_child(), box, flags); ++ } ++}); ++ ++function setStyle(actor, style) { ++ if (!isManualStyling) { ++ actor.set_style(style); ++ } ++} ++ ++function getTweenOpts(opts) { ++ let defaults = { ++ time: animationTime, ++ transition: 'easeInOutQuad' ++ }; ++ ++ return Utils.mergeObjects(opts || {}, defaults); ++} +diff --git a/meson.build b/meson.build +index 6e8c41f6..d4791263 100644 +--- a/meson.build ++++ b/meson.build +@@ -51,6 +51,7 @@ all_extensions = default_extensions + all_extensions += [ + 'auto-move-windows', + 'dash-to-dock', ++ 'dash-to-panel', + 'disable-screenshield', + 'native-window-placement', + 'no-hot-corner', +diff --git a/po/cs.po b/po/cs.po +index 7ce51c90..af40e287 100644 +--- a/po/cs.po ++++ b/po/cs.po +@@ -463,7 +463,7 @@ msgstr "Změnit pozadí…" + msgid "Display Settings" + msgstr "Zobrazit nastavení" + +-#: desktopGrid.js:332 ++#: desktopGrid.js:332 appIcons.js:1726 + msgid "Settings" + msgstr "Nastavení" + +@@ -543,8 +543,1288 @@ msgstr "Zobrazovat koš" + msgid "Show the trash icon in the desktop." + msgstr "Zobrazovat ikonu koše na pracovní ploše." + ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Nahoře, ikony dole" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Vlevo, ikony vpravo" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Nahoře, ikony ukotveny uprostřed" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Vlevo, ikony uprostřed" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Nahoře, plovoucí ikony" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Vlevo, plovoucí ikony" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Uprostřed, na střed monitoru" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Uprostřed, plovoucí" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Uprostřed, plovoucí" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Nad ikonami" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "Vlevo od ikon" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Dole pod ikonami" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "Vpravo od ikon" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Nad systémovou oblastí" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "Vlevo od systémové oblasti" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Pod systémovou oblastí" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "Vpravo od systémové oblasti" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Nad seznamem úloh" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "Vlevo od seznamu úloh" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Pod seznamem úloh" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "Vpravo od seznamu úloh" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Výška tlačítka plochy (px)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Šířka tlačítka plochy (px)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Nastavení indikátoru běžících aplikací" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "Nastavit výchozí hodnoty" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Default (Primární monitor)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Monitor " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Nastavení více monitorů" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Dynamická průhlednost" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Nastavení inteligentního skrývaní (Intellihide)" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Zobrazit ikonu aplikací" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Nastavení plochy" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "Nastavení náhledu oken" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "Nastavení neseskupených aplikací" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "Akce prostředního tlačítko myši" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "Chování prostředního tlačítko myši nad panelem" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "Nastavit chování prostředního tlačítko myši" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "Nastavení dalších klávesových zkratek" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "Nastavení sekundárního menu" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "Pokročilá nastavení" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "Exportovat nastavení" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "Importovat nastavení" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "Zobrazit detaily" ++ ++#: appIcons.js:1398 ++msgid "New Window" ++msgstr "Nové okno" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Ukončit" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "Okna" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "Možnosti napájení" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "Události" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "Systém" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "Spáva zařízení" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "Správa disků" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "Terminál" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "Sledování systému" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "Soubory" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "Odemknout panel úloh" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "Zamknout panel úloh" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "Nastavení Dash to Panel" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "Obnovit okna" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "Zobrazit plochu" ++ ++#: update.js:58 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "Verze %s (%s) je dostupná" ++ ++#: update.js:59 ++msgid "Details" ++msgstr "Zobrazit detaily" ++ ++#: update.js:60 ++msgid "Update" ++msgstr "Aktualizace" ++ ++#: update.js:63 ++msgid "Already up to date" ++msgstr "Používáte aktuální verzi" ++ ++#: update.js:148 ++msgid "Update successful, please log out/in" ++msgstr "Aktualizace proběhla, je nutné se odhlásit a přihlásit" ++ ++#: update.js:149 ++msgid "Log out" ++msgstr "Odhlásit" ++ ++#: update.js:153 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Aktualizace proběhla, restartujte GNOME Shell" ++ ++#: update.js:154 ++msgid "Restart GNOME Shell" ++msgstr "Restartovat GNOME Shell..." ++ ++#: update.js:154 ++msgid "Restarting GNOME Shell..." ++msgstr "Restartuji GNOME Shell..." ++ ++#: update.js:160 ++msgid "Error: " ++msgstr "Chyba: " ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Zatím nedostupné!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Pokud je nastavena minimalizace, pak budou minimalizováno všechna okna " ++"aplikace." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Akce při Shift+Click" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Okno do popředí" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Minimalizovat okno" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Spustit nové okno aplikace" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Procházet okna" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Procházet okna a minimalizovat" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Přepnout náhled jedno/více" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Chování při stisku prostředního tlačítka." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Prostřední tlačítko myši" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Shift + prostřední tlačítko myši." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Akce při Shift + prostřední tlačítko myši" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Oddělit monitory" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Zobrazit oblíbené aplikace na všech monitorech" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Zobrazit hodiny na všech monitorech" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Zobrazit stavovou nabídku na všech monitorech" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Zobrazit položky menu aplikace" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Zobrazit menu Detail" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Zvýraznit aplikaci v popředí" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Hlavní barva ikony" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Vlastní barva" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Průhlednost zvýraznění" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "Výška indikátoru aplikace (px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Hlavní barva ikony - Přepsat nastavení vzhledu" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Barva indikátoru - Přepsat nastavení vzhledu" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 otevřené okno (nebo neseskupené)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Nastavit pro všechny" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 otevřená okna" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 otevřená okna" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4 a více otevřených oken" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Použít jinou pro okna v pozadí" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Velikost fontu (px) titulku aplikace (výchozí 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Velikost fontu titulku aplikace" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "zdědit nastavení tématu" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normální" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "tenčí" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "tučný" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "tučnější" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Barva fontu (px) titulku aplikace" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Maximální šířka titulku aplikace (výchozí 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Použít pevnou šířku titulku aplikací" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Titulky aplikací mají stejnou šířku, i když je text kratší. Maximální " ++"hodnota je použita pro všechny." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Zobrazit indikátor aplikací na pozadí" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Použít ikony oblíbených aplikací jako spouštěče" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Skrýt panel pouze při překrytí okny aplikací " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "Skrývání panelu pro" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Všechna okna" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Okna v popředí" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Maximalizovaná okna" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Vyžaduje podržení myši u okraje obrazovky pro zobrazení panelu" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Citlivost okraje obrazovky při držení myši (px)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Doba držení myši (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Povolit zobrazení panelu v režimu celá obrazovka" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Skrýt pouze sekundární panely (pro více monitorů)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "např. i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Klávesová zkratka pro zobrazení panelu" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Syntaxe: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Rychlost animace zobrazení/skrytí panelu" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Zpoždění před skrytím panelu" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Zpoždění před skrytím při startu (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Pauza před zobrazením náhledu (výchozí 100ms)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Trvání animace (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Pauza před skrytím náhledu (výchozí 100ms)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Okamžitě po kliknutí na ikonu aplikace" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Prostřední tlačítko myši zavře okno v režimu náhledu" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Velikost náhledu okna (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Poměr stran náhledu okna (výška)" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Okraje náhledu oken (px)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Pevný" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Poměr stran náhledu okna (šířka)" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Použít vlastní nastavení průhlednosti pro náhledy" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "Při vypnutí se použije hodnota průhlednosti panelu" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Pozice titulku a tlačítka zavření okna" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Dole" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Nahoře" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Zobrazit titulek okna v náhledech" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Velikost fontu (px) titulku aplikace" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Velikost fontu titulku aplikace" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Barva fontu (px) titulku aplikace" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Povolit režim náhledu okna" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "Rozlišit okna po delším zobrazení náhledu." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Povolit režim náhledu okna po (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "Čas nečinnosti nad ikonou před přechodem do režimu náhledu okna." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Průhlednost režimu náhledu okna" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "Všechna okna, mimo aktivního, mají stejné nastavení průhlednosti." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Prodleva mezi skrolováním myší" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "Omezit počet událostí skrolování myší" ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Win" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Win + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Zkratka" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Zkratky budou buď Win+číslo nebo Win+Alt+číslo" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Nikdy" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Zobrazit dočasně" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Vždy viditelné" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Zobrazit číslo" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "Dočasně zobrazit čísla aplikací při použití klávesových zkratek." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Schovat po (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "např: q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Zkratka pro zobrazení přehledu" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Zobrazit náhled okna při najetí myši" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Zobrazit náhledy pokud má aplikace více otevřených oken" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Číslo řádku" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Numerická klávesnice" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Oba" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Aktivovat klávesové zkratky pomocí" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "Vyberte které klávesy jsou použity k aktivaci klávesových zkratek" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Zobrazit ikonu aplikace" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Vyberte volbu 'Zobrazit ikonu aplikace'" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Vlastní nastavení zobrazení ikony aplikace" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Zobrazit ikonu aplikací s mezerou (px)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Zobrazit pracovní plochu po najetí na tlačítko plochy" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Zpoždění před zobrazením plochy (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Schovat po (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "Nastavení průhlednosti panelu je ovlivněno" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Změnit průhlednost při přiblížení okna (px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Změnit průhlednost (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Rychlost animace zobrazení/skrytí panelu" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Pozice panelu na obrazovce" ++ ++#: Settings.ui.h:145 ++msgid "Left" ++msgstr "Vlevo" ++ ++#: Settings.ui.h:146 ++msgid "Right" ++msgstr "Vpravo" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Pozice panelu" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Umístění hodin" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Hlavní panel zobrazit na" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Zobrazit panel na všech monitorech" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Inteligentní skrývání (Intellihide)" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Zobrazit/skrýt panel podle nastavení" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Umístění" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Výška panelu\n" ++"(výchozí = 48)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Rozestup ikon aplikací\n" ++"(výchozí = 8)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Okraje ikon aplikací\n" ++"(výchozí = 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Pozice indikátoru" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Styl indikátoru běžících aplikací (v popředí)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Tečky" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Čtverce" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Čárkovaný" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Dělený" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Solid" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Styl indikátoru běžících aplikací (v pozadí)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Vlastní barva pozadí panelu " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Vlastní průhlednost panelu" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Průhlednost panelu (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Dynamická průhlednost" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Změnit průhlednost při přiblížení okna" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Vlastní nastavení barevného přechodu panelu " ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Horní barva barevného přechodu a průhlednost (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Dolní barva barevného přechodu a průhlednost (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Vzhled" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Zobrazit oblíbené aplikace" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Zobrazit spuštěné aplikace" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Zobrazit ikonu aplikací" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Animovat zobrazení aplikací." ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Zobrazit tlačítko aktivit" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Zobrazit tlačítko plochy" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Zobrazit tlačítko aplikací" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "Nabídka aplikace > Musí být povoleno v Gnome Tweak Tool" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Zobrazit náhled okna při najetí myši" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Zobrazit tip okna při najetí myši" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Oddělit pracovní plochy" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Neseskupené aplikace" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Chování" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Chování při kliknutí na ikonu běžící aplikace." ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Akce myši" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Přepínat okna" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Akce panelu při skrolování" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Chování prostředního tlačítko myši nad panelem" ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Akce kolečka myši" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Chování kolečka myši nad ikonu běžící aplikace." ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Nedělat nic" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Přepnout plochu" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Procházet okna" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Povolit klávesové zkratky Win+(0-9) ke spouštění aplikací. Lze použít v " ++"kombinaci s Shift a Ctrl." ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "Použít klávesové zkratky pro spouštění aplikací" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "Akce" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "Stavové ikony - velikost fontu (0 = výchozí)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "Levý panel - velikost fontu (0 = výchozí)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Mezery mezi systémovými ikonami\n" ++"(-1 = theme default)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Mezery mezi stavovými ikonami\n" ++"(-1 = výchozí)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Odsazení vlevo\n" ++"(-1 = výchozí)" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "Animovat přepínání oken" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "Animovat spouštěná okna" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Ponechat původní 'gnome-shell dash' (přehled úloh)" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "Aktivovat tlačítka na panelu pouze po stisknutí" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "Nastavení pravého kliku na ikonu aplikace" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "Detailní nastavení" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "verze: " ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Pomocí níže uvedených tlačítek vytvoříte exportujete nastavení do souboru. " ++"Ten lze importovat na jiném počítači." ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "Export a Import nastavení" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "Exportovat do souboru" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "Importovat ze souboru" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "Povolit aktualizace přímo z Github" ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "Aktualizace" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "Pravidelně kontrolovat aktualizace" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "Zkontrolovat teď" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Pozor, nové verze nemusím být ještě " ++"schváleny na portálu extensions.gnome.org! Dozvědět se víc" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Tento program je nabízen bez jakýchkoli záruk.\n" ++"Přečtěte si GNU General Public License, version 2 nebo novější verze." ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "O rozšíření" ++ + #~ msgid "Huge" + #~ msgstr "obrovské" + + #~ msgid "Ok" + #~ msgstr "Ok" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Barva zvýraznění" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Skrýt náhled aplikace po odjetí myši (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Náhled aplikací může mizet velmi rychle při velmi nízkých hodnotách. Při " ++#~ "velkých hodnotách může naopak zůstávat i po najetí na jinou ikonu " ++#~ "aplikace." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Prostřední tlačítko myši zavře okno" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Šířka náhledu oken aplikací (px)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Výška náhledu oken aplikací (px)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Mezery náhledu oken aplikací (px)" ++ ++#~ msgid "Natural" ++#~ msgstr "Přirozené" ++ ++#~ msgid "Left side of panel" ++#~ msgstr "Vlevo na panelu" ++ ++#~ msgid "Centered in content" ++#~ msgstr "Na střed obsahu" ++ ++#~ msgid "Github" ++#~ msgstr "Github" +diff --git a/po/de.po b/po/de.po +index 6bd5c83b..3b6826f3 100644 +--- a/po/de.po ++++ b/po/de.po +@@ -479,7 +479,7 @@ msgstr "Hintergrund ändern …" + msgid "Display Settings" + msgstr "Anzeigeeinstellungen" + +-#: desktopGrid.js:332 ++#: desktopGrid.js:332 appIcons.js:1726 + msgid "Settings" + msgstr "Einstellungen" + +@@ -559,5 +559,1271 @@ msgstr "Papierkorb-Symbol anzeigen" + msgid "Show the trash icon in the desktop." + msgstr "Das Papierkorb-Symbol auf der Arbeitsfläche anzeigen." + ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Oben, mit Erweiterungssymbolen nach unten eingeklappt" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Links, mit Erweiterungssymbolen nach rechts eingeklappt" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Oben, mit fix zentrierten Erweiterungssymbolen" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Links, mit fix zentrierten Erweiterungssymbolen" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Oben, mit beweglich zentrierten Erweiterungssymbolen" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Links, mit beweglich zentrierten Erweiterungssymbolen" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Mitte, fest in der Bildschirmmitte" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Mitte, beweglich zwischen oberen und unteren Elementen" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Mitte, beweglich zwischen linken und rechten Elementen" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Oberhalb der Erweiterungssymbole" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "Links der Erweiterungssymbole" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Unterhalb der Erweiterungssymbole" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "Rechts der Erweiterungssymbole" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Oberhalb der Systemindikatoren" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "Links der Systemindikatoren" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Unterhalb der Systemindikatoren" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "Rechts der Systemindikatoren" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Oberhalb der Anwendungsleiste" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "Links der Anwendungsleiste" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Unterhalb der Anwendungsleiste" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "Rechts der Anwendungsleiste" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Schreibtisch-Schaltflächenhöhe (px)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Schreibtisch-Schaltflächenbreite (px)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Optionen Aktiv-Markierungen" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "Zurücksetzen" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Vorgabe (Primärer Monitor)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Bildschirm " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Optionen Mehrere Bildschirme" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Optionen Dynamische Deckkraft" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Optionen zum automatischen Ausblenden" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Anwendungsoptionen anzeigen" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Schreibtisch-Optionen anzeigen" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "Optionen Fenstervorschau" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "Optionen nicht gruppierter Anwendungen" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "Mittelklick-Verhalten anpassen" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "Leisten-Scroll-Verhalten anpassen" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "Symbol-Scroll-Verhalten anpassen" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "Erweiterte Schnelltastenoptionen" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "Rechtsklickmenü-Optionen" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "Erweiterte Optionen" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "Einstellungen exportieren" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "Einstellungen importieren" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "Details anzeigen" ++ ++#: appIcons.js:1398 ++msgid "New Window" ++msgstr "Neues Fenster" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Schließen" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "Fenster" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "Energieoptionen" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "Ereignislogs" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "System" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "Geräteverwaltung" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "Festplattenverwaltung" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "Terminal" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "Systemüberwachung" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "Dateien" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "Anwendungsleiste entsperren" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "Anwendungsleiste sperren" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "Erweiterungseinstellungen" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "Fenster wiederherstellen" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "Schreibtisch anzeigen" ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Noch nichts!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Falls Minimieren eingestellt ist, minimiert ein Doppelklick alle Fenster der " ++"Anwendung." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Aktion Umschalt+Klick" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Fenster nach vorne holen" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Fenster minimieren" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Neues Fenster öffnen" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Fenster durchwechseln" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Fenster durchwechseln + minimieren" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Einzelumschaltung / Vorschau mehrere" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Verhalten bei einem Mittelklick." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Aktion Mittelklick" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Aktion bei Umschalt+Mittelklick." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Aktion Umschalt+Mittelklick" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Bildschirme isolieren" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Favoriten auf allen Bildschirmen anzeigen" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Uhr auf allen Bildschirmen anzeigen" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Statusmenü auf allen Bildschirmen anzeigen" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Integriere Einträge aus Anwendungsmenü" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Details anzeigen-Menüeintrag" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Fokussierte Anwendung hervorheben" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Dominante Symbolfarbe" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Angepasste Farbe" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Deckkraft Hervorhebung" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "Symbolhöhe (px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Symbolfarbe - Symbol Dominant" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Symbolfarbe - Thema überschreiben" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 Fenster offen (oder nicht gruppiert)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Auf alle anwenden" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 Fenster offen" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 Fenster offen" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4+ Fenster offen" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Andere für nicht fokussierte" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Schriftgröße (px) des Anwendungstitels (14 ist Vorgabe)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Schriftdicke der Anwendungstitel" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "Vom Thema übernehmen" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normal" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "dünner" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "dick" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "dicker" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Schriftfarbe des Anwendungstitels" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Maximale Breite (px) des Anwendungstitels (160 ist Vorgabe)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Feste Breite für Anwendungstitel nutzen" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Die Anwendungstitel haben alle die gleiche Breite, selbst wenn der Text " ++"kürzer ist als die maximale Breite. Die maximale Breite wird als feste " ++"Breite genutzt." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Läuft-Indikatoren auf nicht fokussierten Anwendungen anzeigen" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Favoritensymbole als Anwendungsstarter nutzen" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Leiste nur bei Überschneidung mit Fenstern ausblenden " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "Die Leiste weicht aus" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Alle Fenster" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Fokussierte Fenster" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Maximierte Fenster" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Druckschwelle am Rand zum Einblenden der Leiste" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Benötigte Druckschwelle (px)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Benötigte Druckverzögerung (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Einblenden der Leiste im Vollbildmodus erlauben" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Nur sekundäre Leisten ausblenden (benötigt Option Mehrere Bildschirme)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "z.B. i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Tastenkürzel zum Einblenden und Halten der Leiste" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Syntax: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Ein-/Ausblenddauer (ms)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Verzögerung vor dem Ausblenden (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Verzögerung des automatischen Ausblendens beim Start (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Verzögerung (ms) beim Einblenden (Standard ist 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Animationszeit (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Verzögerung (ms) beim Ausblenden (Vorgabe ist 100)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Sofort beim Klick auf das Anwendungssymbol" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Mittelklick auf Vorschau zum Schließen des Fensters" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Bevorzugte Fenstervorschaugröße (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Fenstervorschau Format Y (Höhe)" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Abstand Fenstervorschau (px)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Fest" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Fenstervorschau Format X (Breite)" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Angepasste Deckkraft für Vorschauhintergrund" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Falls deaktiviert, hat der Vorschauhintergrund die gleiche Deckkraft wie die " ++"Leiste" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Schließenschaltfläche und Position Fenstertitel" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Unten" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Oben" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Fenstertitel in Vorschau anzeigen" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Schriftgröße (px) des Vorschauanwendungstitels" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Schriftdicke des Vorschauanwendungstitels" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Schriftfarbe des Vorschauanwendungstitels" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Fensterhervorhebung aktivieren" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Wenn der Mauszeiger über einer Fenstervorschau verweilt, wird das Fenster " ++"hervorgehoben." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Zeitgrenze zur Aktivierung der Fensterhervorhebung (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Verzögerung, während der der Mauszeiger über einer Fenstervorschau bleiben " ++"muss, um die Fensterhervorhebung zu aktivieren." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Deckkraft Fensterhervorhebung" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"Die Deckkraft aller Fenster, außer dem hervorgehobenen, hat denselben Wert." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Verzögerung zwischen Maus-Scroll-Ereignissen (ms)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "Dieser Wert limitiert die Anzahl akzeptierter Maus-Scroll-Ereignisse." ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Schnelltasten-Präfix" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Schnelltasten sind entweder Super+Nummer oder Super+Alt+Nummer" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Nie" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Vorübergehend anzeigen" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Immer sichtbar" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Nummern-Overlay" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Zeige Anwendungsnummern über Symbolen, während Schnelltasten gedrückt werden." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Ausblendeverzögerung (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "z.B. q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Kürzel zum Anzeigen der Nummern für 2 Sekunden" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Fenstervorschau per Tastenkürzel einblenden" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Vorschau anzeigen, wenn Anwendungen mehrere Fenster hat" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Nummernreihe" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Zahlenfeld" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Beide" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Schnelltasten aktivieren mit" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "Auswählen, welche Zahlenfeldtasten die Schnelltasten aktivieren" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Aktuelles Anwendungen anzeigen-Symbol" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Anwendungen anzeigen-Symbol auswählen" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Angepasstes Anwendungen anzeigen-Symbol" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Seitenabstand bei Anwendungssymbolen anzeigen (px)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Schreibtisch zeigen, wenn Maus die Schreibtischschaltfläche berührt" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Verzögerung beim Zeigen des Schreibtischs (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Ausblendedauer (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "Die Deckkraft des Leistenhintergrunds wird beeinflusst durch" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Deckkraft ändern, wenn Fenster näher kommt als (px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Deckkraft ändern zu (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Animationsdauer Änderung Deckkraft (ms)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Position der Leiste" ++ ++#: Settings.ui.h:145 ++msgid "Left" ++msgstr "Links" ++ ++#: Settings.ui.h:146 ++msgid "Right" ++msgstr "Rechts" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Position Anwendungsleiste" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Position der Uhr" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Hauptleiste anzeigen auf" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Leisten auf allen Bildschirmen anzeigen" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Automatischen Ausblenden" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Leiste entsprechend der Einstellungen ein-/ausblenden" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Position" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Leistengröße\n" ++"(48 ist Standard)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Symbolabstand\n" ++"(8 ist Standard)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Symbolabstand\n" ++"(Vorgabewert ist 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Position Aktiv-Markierung" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Stil Aktiv-Markierung (fokussierte Anwendung)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Punkte" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Quadrate" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Striche" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Unterteilt" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Fest" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Stil Aktiv-Markierung (nicht fokussierte Anwendung)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Leistenhintergrundfarbe des Themas überschreiben " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Leistenhintergrunddeckkraft des Themas überschreiben" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Leistenhintergrunddeckkraft (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Dynamische Hintergrunddeckkraft" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Deckkraft ändern, wenn Fenster der Leiste nahe kommt" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Verlauf des Themas überschreiben " ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Obere Farbe und Deckkraft des Verlaufs (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Untere Farbe und Deckkraft des Verlaufs (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Stil" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Favoritensymbole anzeigen" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Laufende Anwendungen anzeigen" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Anwendungen-Symbol anzeigen" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Animation bei Anwendungen einblenden." ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Aktivitäten-Schaltfläche anzeigen" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Schreibtisch-Schaltfläche anzeigen" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Anwendungsmenü-Schaltläche anzeigen" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Obere Leiste > Anwendungsmenü anzeigen muss aktiviert sein im " ++"Optimierungswerkzeug (Tweak Tool)" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Fenstervorschau bei Berührung einblenden" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Kurzinfo bei Berührung" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Arbeitsflächen isolieren" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Anwendungen nicht gruppieren" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Verhalten" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Verhalten beim Anklicken des Symbols einer laufenden Anwendung." ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Klickaktion" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Fenster umschalten" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Leisten-Scrollen" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Verhalten beim Scrollen über der Leiste." ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Symbol-Scrollen" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Verhalten beim Scrollen über ein Anwendungssymbol." ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Nichts tun" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Arbeitsfläche wechseln" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Fenster durchwechseln" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Super+(0-9) als Kürzel zum Aktivieren von Anwendungen nutzen. Kann auch mit " ++"Strg und Umschalttaste genutzt werden." ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "Schnelltasten zum Aktivieren von Anwendungen nutzen" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "Aktion" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Schriftgröße Benachrichtigungsbereich\n" ++"(0 = Themenstandard)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Schriftgröße linker Teil\n" ++"(0 = Themenstandard)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Symbolabstand Benachrichtigungsbereich\n" ++"(-1 = Themenstandard)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Statussymbolabstand\n" ++"(-1 = Themenstandard)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "Elementabstand linker Teil" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "Wechsel zwischen Anwendungen animieren" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "Öffnen von Anwendungen animieren" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Originale Anwendungsleiste der GNOME Shell behalten (Übersicht)" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "" ++"Menüschaltflächen der Leiste (z.B. Datumsmenü) nur per Klick aktivieren" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "Anwendungsrechtsklickmenü" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "Feineinstellung" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "Version: " ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Mit den Schaltflächen lässt sich eine Konfigdatei mit den aktuellen " ++"Einstellungen erstellen, die sich auf einem anderen Rechner importieren " ++"lässt." ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "Einstellungen ex- und importieren" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "In Datei exportieren" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "Aus Datei importieren" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Erlaubt das Aktualisieren der Erweiterung direkt vom GitHub-Repository." ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "Aktualisierungen" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "Regelmäßig auf verfügbare Aktualisierungen prüfen" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "Jetzt prüfen" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Achtung, diese offiziellen " ++"Veröffentlichungen von Dash to Panel sind möglicherweise noch nicht von " ++"extensions.gnome.org geprüft! Weiterlesen" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Für dieses Programm besteht KEINERLEI GARANTIE.\n" ++"Details unter GNU General Public License, version 2 or later" ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "Info" ++ + #~ msgid "Huge" + #~ msgstr "Riesig" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Farbe Hervorhebung" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Verzögerung beim Ausblenden von Fenstervorschau (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Wenn zu niedrig eingestellt, scheint die Fenstervorschau zu schnell zu " ++#~ "schließen, wenn man versucht, mit der Maus die Vorschau anzuklicken. " ++#~ "Falls zu hoch eingestellt, dann scheint die Fenstervorschau zu hängen, " ++#~ "wenn man zum nächsten Fenster wechselt." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Mittelklick zum Fensterschließen" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Breite der Fenstervorschau (px)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Höhe der Fenstervorschau (px)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Abstand zwischen Fenstervorschau (px)" ++ ++#~ msgid "Natural" ++#~ msgstr "Natürlich" ++ ++#~ msgid "Left side of panel" ++#~ msgstr "Linke Seite der Leiste" ++ ++#~ msgid "Centered in content" ++#~ msgstr "Am Inhalt zentriert" ++ ++#~ msgid "Github" ++#~ msgstr "Github" ++ ++#~ msgid "Height (px)" ++#~ msgstr "Höhe (px)" ++ ++#~ msgid "Color - Override Theme" ++#~ msgstr "Farbe - Thema überschreiben" ++ ++#~ msgid "1 window open" ++#~ msgstr "1 Fenster offen" +diff --git a/po/es.po b/po/es.po +index ee30c8ae..aae82532 100644 +--- a/po/es.po ++++ b/po/es.po +@@ -488,7 +488,7 @@ msgstr "Abrir en una terminal" + msgid "Change Background…" + msgstr "Cambiar el fondo..." + +-#: desktopGrid.js:335 ++#: desktopGrid.js:335 appIcons.js:1793 + msgid "Settings" + msgstr "Configuración" + +@@ -568,6 +568,1301 @@ msgstr "Mostrar la papelera" + msgid "Show the trash icon in the desktop." + msgstr "Mostrar la papelera en el escritorio." + ++#: Settings.ui.h:145 ++#, fuzzy ++msgid "Left" ++msgstr "" ++"#-#-#-#-# es.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Izquierda\n" ++"#-#-#-#-# es.po #-#-#-#-#\n" ++"A la izquierda" ++ ++#: Settings.ui.h:146 ++#, fuzzy ++msgid "Right" ++msgstr "" ++"#-#-#-#-# es.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Derecha\n" ++"#-#-#-#-# es.po #-#-#-#-#\n" ++"A la derecha" ++ ++#: appIcons.js:1429 ++msgid "New Window" ++msgstr "Ventana nueva" ++ ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Arriba, con iconos contraídos" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "A la izquierda, con iconos contraídos a la derecha" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Arriba, con iconos fijos centrados" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "A la izquierda, con iconos fijos centrados" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Arriba, con iconos flotantes centrados" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "A la izquierda, con iconos flotantes centrados" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Centrado, fijo en mitad del monitor" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Centrado, flotando entre los elementos superiores e inferiores" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Centrado, flotando entre los elementos de la izquierda y derecha" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Arriba de los iconos" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "A la izquierda de los iconos" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Abajo de los iconos" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "A la derecha de los iconos" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Arriba de los indicadores del sistema" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "A la izquierda de los indicadores del sistema" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Abajo de los indicadores del sistema" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "A la derecha de los indicadores del sistema" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Arriba de la barra de tareas" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "A la izquierda de la barra de tareas" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Abajo de la barra de tareas" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "A la derecha de la barra de tareas" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Alto del botón Mostrar Escritorio (px)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Ancho del botón Mostrar Escritorio (px)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Opciones del indicador de ejecución" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1084 prefs.js:1331 prefs.js:1415 prefs.js:1480 ++#: prefs.js:1516 prefs.js:1613 prefs.js:1647 prefs.js:1689 ++msgid "Reset to defaults" ++msgstr "Restablecer los valores predeterminados" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Por defecto (Monitor principal)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Monitor " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Opciones Muti-monitores" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Opciones de opacidad dinámica" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Opciones de ocultación inteligente" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Mostrar las opciones de aplicación" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Mostrar el Escritorio" ++ ++#: prefs.js:1077 ++msgid "Window preview options" ++msgstr "Opciones de vista rápida de ventanas" ++ ++#: prefs.js:1324 ++msgid "Ungrouped application options" ++msgstr "Opciones de ventanas no combinadas" ++ ++#: prefs.js:1408 ++msgid "Customize middle-click behavior" ++msgstr "Personalizar comportamiento del botón central" ++ ++#: prefs.js:1473 ++msgid "Customize panel scroll behavior" ++msgstr "Personalizar comportamiento del desplazamiento del panel" ++ ++#: prefs.js:1509 ++msgid "Customize icon scroll behavior" ++msgstr "Personalizar comportamiento del desplazamiento de los iconos" ++ ++#: prefs.js:1606 ++msgid "Advanced hotkeys options" ++msgstr "Opciones avanzadas de atajos de teclado" ++ ++#: prefs.js:1640 ++msgid "Secondary Menu Options" ++msgstr "Opciones del menú secundario" ++ ++#: prefs.js:1682 Settings.ui.h:226 ++msgid "Advanced Options" ++msgstr "Opciones avanzadas" ++ ++#: prefs.js:1774 ++msgid "Export settings" ++msgstr "Exportar configuraciones" ++ ++#: prefs.js:1791 ++msgid "Import settings" ++msgstr "Importar configuraciones" ++ ++#: appIcons.js:1411 ++msgid "Show Details" ++msgstr "Mostrar detalles" ++ ++#: appIcons.js:1429 appIcons.js:1489 appIcons.js:1491 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Salir" ++ ++#: appIcons.js:1491 ++msgid "Windows" ++msgstr "Ventanas" ++ ++#: appIcons.js:1745 ++msgid "Power options" ++msgstr "Energía" ++ ++#: appIcons.js:1750 ++msgid "Event logs" ++msgstr "Registros" ++ ++#: appIcons.js:1755 ++msgid "System" ++msgstr "Sistema" ++ ++#: appIcons.js:1760 ++msgid "Device Management" ++msgstr "Pantallas" ++ ++#: appIcons.js:1765 ++msgid "Disk Management" ++msgstr "Discos" ++ ++#: appIcons.js:1773 ++msgid "Terminal" ++msgstr "Terminal" ++ ++#: appIcons.js:1778 ++msgid "System monitor" ++msgstr "Monitor del sistema" ++ ++#: appIcons.js:1783 ++msgid "Files" ++msgstr "Carpeta personal" ++ ++#: appIcons.js:1788 ++msgid "Extensions" ++msgstr "Extensiones" ++ ++#: appIcons.js:1800 ++msgid "Unlock taskbar" ++msgstr "Desbloquear barra de tareas" ++ ++#: appIcons.js:1800 ++msgid "Lock taskbar" ++msgstr "Bloquear barra de tareas" ++ ++#: appIcons.js:1805 ++msgid "Dash to Panel Settings" ++msgstr "Opciones de Dash to Panel" ++ ++#: appIcons.js:1818 ++msgid "Restore Windows" ++msgstr "Restaurar ventanas" ++ ++#: appIcons.js:1818 ++msgid "Show Desktop" ++msgstr "Mostrar el Escritorio" ++ ++#: update.js:48 ++msgid "Unavailable when installed from extensions.gnome.org" ++msgstr "No disponible cuando se instala desde extensions.gnome.org" ++ ++#: update.js:62 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "La versión %s (%s) está disponible" ++ ++#: update.js:63 ++msgid "Details" ++msgstr "Mostrar detalles" ++ ++#: update.js:64 ++msgid "Update" ++msgstr "Actualizar" ++ ++#: update.js:67 ++msgid "Already up to date" ++msgstr "Ya está actualizado" ++ ++#: update.js:75 ++msgid "Error: " ++msgstr "Error: " ++ ++#: update.js:168 ++msgid "Update successful, please log out/in" ++msgstr "Actualización correcta, por favor, cierre e inicie sesión" ++ ++#: update.js:169 ++msgid "Log out" ++msgstr "Cerrar sesión" ++ ++#: update.js:173 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Actualización correcta, por favor, restaure GNOME Shell" ++ ++#: update.js:174 ++msgid "Restart GNOME Shell" ++msgstr "Restarurar GNOME Shell" ++ ++#: update.js:174 ++msgid "Restarting GNOME Shell..." ++msgstr "Restaurando GNOME Shel..." ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "¡Nada aún!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Cuando está seleccionado minimizar, doble pulsación minimiza todas las " ++"ventanas de la aplicación." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Acción de Mayúsculas+Click" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Elevar ventanas" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Minimizar ventana" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Lanzar una nueva instancia" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Alternar entre ventanas" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Alternar ventanas y minimizar" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Alternar entre simple y vista rápida múltiple" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Comportamiento del botón central" ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Acción del botón central" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Comportamiento para Mayúsculas+Botón-Central" ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Acción de Mayúsculas+Botón-Central" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Aislar los espacios de trabajo" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Mostrar aplicaciones favoritas en todos los espacios de trabajo" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Mostrar reloj en todos los espacios de trabajo" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Mostrar el menú de estado en todos los espacios de trabajo" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Integrar los elementos del Menú de aplicación" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Mostrar detalles del menú de elementos" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Resaltar la aplicación activa" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Color del icono predominante" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Color personalizado" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Opacidad de resaltado" ++ ++#: Settings.ui.h:25 ++msgid "Indicator size (px)" ++msgstr "Tamaño del indicador (px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Color del indicador - Predominar el icono" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Color del indicador - Predominar sobre el tema" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 ventana abierta (o no combinada)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Aplicar a todo" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 ventanas abiertas" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 ventanas abiertas" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4 o más ventanas abiertas" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Usar diferente para desenfoque" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "" ++"Tamaño de la fuente (px) para los títulos de aplicación (14 por defecto)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Tamaño de la fuente para los títulos de aplicación" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "heredado del tema" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normal" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "más fino" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "en negrita" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "más en negrita" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Color de letra de los títulos de aplicación" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Ancho máximo (px) de los títulos de aplicación (160 por defecto)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Usar ancho fijo para los títulos de aplicación" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Todos los títulos de aplicación tienen el mismo ancho, aun si el texto es " ++"más corto que el ancho máximo. El ancho máximo es usado como valor fijo." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Estilo de los indicadores de ejecución (aplicación no enfocada)" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Usar los iconos favoritos como lanzadores de aplicación" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Esconder el panel sólo cuando es obstruido por ventanas" ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "El panel se esconde de" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Todas las ventanas" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Ventanas activas" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Ventanas maximizadas" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Requerir presión en el borde de la pantalla para mostrar el panel" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Presión mínima requerida (px)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Tiempo de activación (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "En modo pantalla completa, permitir que el panel sea mostrado" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Ocultar sólo los paneles secundarios (requiere opción multi-monitor)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "p.e. i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Atajos del teclado para mostrar y mantener el panel" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Sintáxis: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Duración de ocultar y mostrar animaciones (ms)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Tiempo antes de ocultar el panel (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Tiempo antes de habilitar el panel inteligente (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Tiempo (ms) antes de mostrar (100 por defecto)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Tiempo de la animación (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Tiempo (ms) antes de ocultar (100 por defecto)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Pulsación inmediata en icono de aplicación" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Usar el botón central en la vista rápida para cerrar la ventana" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Tamaño por defecto de las vistas rápidas (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Altura de la vista rápida de ventanas" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Relleno (px) de la vista rápida de ventanas" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Anchura de la vista rápida de ventanas" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Usar opacidad personalizada para el fondo de las vistas rápidas" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Si está deshabilitado, el fondo de las vistas rápidas tienen la misma " ++"opacidad que la del panel" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Botón de apagado y posición de los títulos" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Abajo" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Arriba" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Mostrar los títulos de las ventanas en las vistas rápidas" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Tamaño de letra (px) de los títulos de aplicación (14 por defecto)" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Color de letra de los títulos de aplicación" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Color de letra de los títulos de aplicación" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Habilitar ojeada rápida de ventana" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Al desplazar el ratón sobre una vista rápida de ventana, la ventana es " ++"resaltada." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Tiempo para activar el modo de ojeada rápida (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Tiempo de inactividad al desplazar el ratón sobre una vista rápida de " ++"ventana para activar el modo de ojeada rápida." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Opacidad del modo de ojeada rápida" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "Todas las ventanas excepto la resaltada tienen la misma opacidad fija." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Retraso entre eventos de desplazamiento del ratón (ms)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Usar este valor para limitra el número de eventos de desplazamiento " ++"capturados del ratón" ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Súper" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Súper + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Prefijo de atajo de teclado" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Los atajos serán Súper+Núm. o Súper+Alt+Núm." ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Nunca" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Mostrar temporalmente" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Siempre visible" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Número de aplicación" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Al usar atajos, mostrar momentáneamente el número de aplicación sobre los " ++"íconos." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Tiempo de ocultación (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "p.e. q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Atajo para mostrar el número de aplicación por 2 segundos" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Mostrar vista rápida de ventanas al pasar con el ratón" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Mostrar vistas previas cuando la aplicación tiene múltiples instancias" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Fila numérica" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Teclado numérico" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Ambos" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Usar atajos de teclado para activar aplicaciones" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Selecciona qué teclas numéricas se usan para activar los atajos de teclado" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Icono actual de Mostrar aplicaciones" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Seleccionar un icono Mostrar aplicaciones" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Icono Mostrar aplicaciones personalizado" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Tamaño de relleno (px) de Mostrar aplicaciones" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Mostrar escritorio al colocar el botón Mostrar Escritorio" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Tiempo antes de ocultar el panel (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Tiempo de ocultación (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "La opacidad del fondo del panel está afectada por" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Cambiar la opacidad cuando una ventana se aproxima (px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Cambiar la opacidad a (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Duración de las animaciones (ms)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Posición del panel en la pantalla" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Posición de la barra de tareas" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Posición del reloj" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Mostrar el panel principal en" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Mostrar los paneles en todos los espacios de trabajo" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Ocultación inteligente del panel" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Ocultar y mostrar el panel de acuerdo con las preferencias" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Posición" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Tamaño del panel\n" ++"(48 por defecto)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Margen de los íconos\n" ++"(8 por defecto)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Relleno de los íconos\n" ++"(4 por defecto)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Posición de los indicadores de ejecución" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Estilo de los indicadores de ejecución (aplicación enfocada)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Puntos" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Cuadrados" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Guiones" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Segmentado" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Sólido" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Estilo de los indicadores de ejecución (aplicación no enfocada)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Cambiar el color de fondo del tema del panel " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Cambiar la opacidad de fondo del tema del panel" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Opacidad del fondo del panel (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Opacidad dinámica del fondo" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Cambiar la opacidad cuando una ventana se aproxima al panel" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Cambiar el gradiente del tema del panel" ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Color y opacidad del gradiente superior (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Color y opacidad del gradiente inferior (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Estilo" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Mostrar aplicaciones favoritas" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Mostrar aplicaciones en ejecución" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Mostrar el icono Aplicaciones" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Animar Mostrar Aplicaciones" ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Mostrar el botón Actividades" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Mostrar el botón Escritorio" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Mostrar el botón Menú de Aplicación" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Barra superior > Mostrar menú de aplicación habilitado en Herramienta de " ++"retoques." ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Mostrar vista rápida de ventanas al pasar con el ratón" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Mostrar barra de herramientas al pasar con el ratón" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Aislar los espacios de trabajo" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Desagrupar aplicaciones" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Comportamiento" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Comportamiento al pulsar el ícono de una aplicación en ejecución" ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Acción de pulsación" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Alternar ventanas" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Acción del panel de desplazamiento" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Comportamiento cuando el ratón de desplaza en el panel" ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Acción al desplazar iconos" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "" ++"Comportamiento cuando el ratón se desplaza sobre el icono de una aplicación" ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "No hacer nada" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Cambiar espacio de trabajo" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Alternar entre ventanas" ++ ++#: Settings.ui.h:205 ++msgid "Change volume" ++msgstr "Cambiar el volumen" ++ ++#: Settings.ui.h:206 ++msgid "Same as panel" ++msgstr "La misma que el panel" ++ ++#: Settings.ui.h:207 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Habilitar Súper+(0-9) como atajos para activar aplicaciones. También puede " ++"ser usado junto con Mayús. y Ctrl." ++ ++#: Settings.ui.h:208 ++msgid "Use hotkeys to activate apps" ++msgstr "Usar atajos de teclado para activar aplicaciones" ++ ++#: Settings.ui.h:209 ++msgid "Action" ++msgstr "Acción" ++ ++#: Settings.ui.h:210 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tamaño de fuente en la bandeja del sistema\n" ++"(0 = predeterminado)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tamaño de fuente en la zona izquierda\n" ++"(0 = predeterminado)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Separación en la bandeja del sistema\n" ++"(-1 = predeterminado)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Separación de los íconos de estado\n" ++"(-1 = predeterminado)" ++ ++#: Settings.ui.h:218 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Separación en la zona izquierda\n" ++"(-1 = predeterminado)" ++ ++#: Settings.ui.h:220 ++msgid "Animate switching applications" ++msgstr "Animar al cambiar de aplicación" ++ ++#: Settings.ui.h:221 ++msgid "Animate launching new windows" ++msgstr "Animar al abrir nuevas ventanas" ++ ++#: Settings.ui.h:222 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Conservar el dash original de gnome-shell (vista principal)" ++ ++#: Settings.ui.h:223 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "" ++"Activar los botones del menú del panel (p.e. menú de fecha) sólo al pulsar" ++ ++#: Settings.ui.h:224 ++msgid "Force Activities hot corner on primary monitor" ++msgstr "" ++"Forzar las actividades de la esquina 'caliente' en el monitor principal" ++ ++#: Settings.ui.h:225 ++msgid "App icon secondary (right-click) menu" ++msgstr "Menú secundario (click derecho) de aplicación" ++ ++#: Settings.ui.h:227 ++msgid "Fine-Tune" ++msgstr "Retoques" ++ ++#: Settings.ui.h:228 ++msgid "version: " ++msgstr "versión: " ++ ++#: Settings.ui.h:229 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:230 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Usar los botones de abajo para crear el fichero de configuración con tus " ++"preferenciasactuales para poder ser importadas de otra máquina." ++ ++#: Settings.ui.h:231 ++msgid "Export and import settings" ++msgstr "Exportar e importar configuración" ++ ++#: Settings.ui.h:232 ++msgid "Export to file" ++msgstr "Exportar a un fichero" ++ ++#: Settings.ui.h:233 ++msgid "Import from file" ++msgstr "Importar de un fichero" ++ ++#: Settings.ui.h:234 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Esto te permite actualizar la extensión directamente del repositorio GitHub" ++ ++#: Settings.ui.h:235 ++msgid "Updates" ++msgstr "Actualizaciones" ++ ++#: Settings.ui.h:236 ++msgid "Periodically check for updates" ++msgstr "Comprobar periódicamente actualizaciones" ++ ++#: Settings.ui.h:237 ++msgid "Check now" ++msgstr "Comprobar ahora" ++ ++#: Settings.ui.h:238 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"¡Sé consciente de que estas " ++"versiones oficiales de 'Dash to Panel' podrían no estar todavía revisadas en " ++"extensions.gnome.org! Leer más" ++ ++#: Settings.ui.h:239 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Este programa viene SIN NINGUNA GARANTÍA.\n" ++"Consulte la Licencia Pública General de GNU, versión 2 o posterior para obtener " ++"más detalles." ++ ++#: Settings.ui.h:241 ++msgid "About" ++msgstr "Acerca de" ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -604,12 +1899,6 @@ msgstr "Mostrar la papelera en el escritorio." + #~ msgid "Normal" + #~ msgstr "Normal" + +-#~ msgid "Left" +-#~ msgstr "Izquierda" +- +-#~ msgid "Right" +-#~ msgstr "Derecha" +- + #~ msgid "Upside-down" + #~ msgstr "Hacia abajo" + +@@ -644,9 +1933,6 @@ msgstr "Mostrar la papelera en el escritorio." + #~ msgid "Drag here to add favorites" + #~ msgstr "Arrastrar aquí para añadir a favoritos" + +-#~ msgid "New Window" +-#~ msgstr "Ventana nueva" +- + #~ msgid "Quit Application" + #~ msgstr "Salir de la aplicación" + +@@ -893,3 +2179,42 @@ msgstr "Mostrar la papelera en el escritorio." + + #~ msgid "Shows the Videos folder in the desktop." + #~ msgstr "Muestra la carpeta Vídeos en el escritorio." ++ ++#~ msgid "Highlight color" ++#~ msgstr "Color de resaltado" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Tiempo para cerrar la vista rápida (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Si el valor es muy chico, la ventana de vista rápida parecerá cerrarse " ++#~ "muy rápidamente al intentar usar el menú. Si el valor es muy grande, la " ++#~ "vista rápida no desaparecerá al ir a un ícono adyacente." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Click central para cerrar ventana" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Ancho de las vistas rápidas de ventanas (px)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Altura de las vistas rápidas de ventanas (px)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Margen de las vistas rápidas de ventanas (px)" ++ ++#~ msgid "Natural" ++#~ msgstr "Natural" ++ ++#~ msgid "Left side of panel" ++#~ msgstr "Lado izquierdo del panel" ++ ++#~ msgid "Centered in content" ++#~ msgstr "Centrado en el contenido" ++ ++#~ msgid "Github" ++#~ msgstr "Github" +diff --git a/po/fr.po b/po/fr.po +index 6961fa43..056e575b 100644 +--- a/po/fr.po ++++ b/po/fr.po +@@ -487,6 +487,1254 @@ msgstr "Montrer l’icône de la corbeille" + msgid "Show the trash icon in the desktop." + msgstr "Montrer la corbeille sur le bureau." + ++#: prefs.js:206 ++msgid "Show Desktop button height (px)" ++msgstr "Hauteur du bouton Afficher le Bureau (px)" ++ ++#: prefs.js:206 ++msgid "Show Desktop button width (px)" ++msgstr "Longueur du bouton Afficher le Bureau (px)" ++ ++#: prefs.js:218 ++msgid "Unavailable when gnome-shell top panel is present" ++msgstr "Indisponible quand le panneau de gnome-shell est présent" ++ ++#: prefs.js:293 ++msgid "Show Applications button" ++msgstr "Bouton Afficher les Applications" ++ ++#: prefs.js:294 ++msgid "Activities button" ++msgstr "Bouton Activités" ++ ++#: prefs.js:295 ++msgid "Taskbar" ++msgstr "Barre des tâches" ++ ++#: prefs.js:296 ++msgid "Date menu" ++msgstr "Horloge" ++ ++#: prefs.js:297 ++msgid "System menu" ++msgstr "Menu système" ++ ++#: prefs.js:298 ++msgid "Left box" ++msgstr "Zone gauche" ++ ++#: prefs.js:299 ++msgid "Center box" ++msgstr "Zone centre" ++ ++#: prefs.js:300 ++msgid "Right box" ++msgstr "Zone droite" ++ ++#: prefs.js:301 ++msgid "Desktop button" ++msgstr "Bouton Afficher le Bureau" ++ ++#: prefs.js:307 ++msgid "Move up" ++msgstr "Déplacer vers le haut" ++ ++#: prefs.js:309 ++msgid "Move down" ++msgstr "Déplacer vers le bas" ++ ++#: prefs.js:311 ++msgid "Visible" ++msgstr "Visible" ++ ++#: prefs.js:312 ++msgid "Select element position" ++msgstr "Sélectionner la position de l'élément" ++ ++#: prefs.js:323 ++msgid "Stacked to top" ++msgstr "Empilé en haut" ++ ++#: prefs.js:323 ++msgid "Stacked to left" ++msgstr "Empilé à gauche" ++ ++#: prefs.js:324 ++msgid "Stacked to bottom" ++msgstr "Empilé en bas" ++ ++#: prefs.js:324 ++msgid "Stacked to right" ++msgstr "Empilé à droite" ++ ++#: prefs.js:325 ++msgid "Centered" ++msgstr "Centré" ++ ++#: prefs.js:326 ++msgid "Monitor Center" ++msgstr "Centre de l'écran " ++ ++#: prefs.js:345 ++msgid "More options" ++msgstr "Plus d'options" ++ ++#: prefs.js:369 ++msgid "Show Applications options" ++msgstr "Options du bouton Afficher les Applications" ++ ++#: prefs.js:376 prefs.js:433 prefs.js:576 prefs.js:894 prefs.js:1019 ++#: prefs.js:1146 prefs.js:1405 prefs.js:1500 prefs.js:1565 prefs.js:1608 ++#: prefs.js:1705 prefs.js:1739 prefs.js:1781 ++msgid "Reset to defaults" ++msgstr "Restaurer paramètres" ++ ++#: prefs.js:426 ++msgid "Show Desktop options" ++msgstr "Options du bouton Afficher le Bureau" ++ ++#: prefs.js:569 ++msgid "Running Indicator Options" ++msgstr "Options de l'indicateur d'activité" ++ ++#: prefs.js:732 ++msgid "Primary monitor" ++msgstr "Écran principal" ++ ++#: prefs.js:732 ++msgid "Monitor " ++msgstr "Écran " ++ ++#: prefs.js:887 ++msgid "Dynamic opacity options" ++msgstr "Options d'opacité dynamique" ++ ++#: prefs.js:1012 ++msgid "Intellihide options" ++msgstr "Options du masquage intelligent" ++ ++#: prefs.js:1139 ++msgid "Window preview options" ++msgstr "Options de la prévisualisation" ++ ++#: prefs.js:1398 ++msgid "Ungrouped application options" ++msgstr "Options des applications dégroupées" ++ ++#: prefs.js:1493 ++msgid "Customize middle-click behavior" ++msgstr "Modifier l'action du clic de la molette" ++ ++#: prefs.js:1558 ++msgid "Customize panel scroll behavior" ++msgstr "Modifier l'action du défilement de la souris sur le panneau" ++ ++#: prefs.js:1601 ++msgid "Customize icon scroll behavior" ++msgstr "Modifier l'action du défilement de la souris sur une application" ++ ++#: prefs.js:1698 ++msgid "Advanced hotkeys options" ++msgstr "Raccourcis avancés" ++ ++#: prefs.js:1732 ++msgid "Secondary Menu Options" ++msgstr "Options du menu secondaire" ++ ++#: prefs.js:1774 Settings.ui.h:226 ++msgid "Advanced Options" ++msgstr "Options avancées" ++ ++#: prefs.js:1877 ++msgid "Export settings" ++msgstr "Exporter les paramètres" ++ ++#: prefs.js:1894 ++msgid "Import settings" ++msgstr "Importer des paramètres" ++ ++#: appIcons.js:1431 ++msgid "Show Details" ++msgstr "Afficher les détails" ++ ++#: appIcons.js:1449 ++msgid "New Window" ++msgstr "Nouvelle fenêtre" ++ ++#: appIcons.js:1449 appIcons.js:1509 appIcons.js:1511 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Quitter" ++ ++#: appIcons.js:1511 ++msgid "Windows" ++msgstr "Fenêtres" ++ ++#: appIcons.js:1858 ++msgid "Unlock taskbar" ++msgstr "Déverrouiller la barre des tâches" ++ ++#: appIcons.js:1858 ++msgid "Lock taskbar" ++msgstr "Verrouiller la barre des tâches" ++ ++#: appIcons.js:1863 ++msgid "Dash to Panel Settings" ++msgstr "Paramètres Dash to Panel" ++ ++#: appIcons.js:1876 ++msgid "Restore Windows" ++msgstr "Restaurer les fenêtres" ++ ++#: appIcons.js:1876 ++msgid "Show Desktop" ++msgstr "Afficher le bureau" ++ ++#: update.js:48 ++msgid "Unavailable when installed from extensions.gnome.org" ++msgstr "Indisponible lorsqu'installé depuis extensions.gnome.org" ++ ++#: update.js:62 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "La version %s (%s) est disponible" ++ ++#: update.js:63 ++msgid "Details" ++msgstr "Détails" ++ ++#: update.js:64 ++msgid "Update" ++msgstr "Mettre à jour" ++ ++#: update.js:67 ++msgid "Already up to date" ++msgstr "Déjà à jour" ++ ++#: update.js:75 ++msgid "Error: " ++msgstr "Erreur: " ++ ++#: update.js:168 ++msgid "Update successful, please log out/in" ++msgstr "" ++"Mise à jour complétée avec succès, veuillez fermer/ouvrir votre session" ++ ++#: update.js:169 ++msgid "Log out" ++msgstr "Fermer la session" ++ ++#: update.js:173 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Mise à jour complétée avec succès, veuillez redémarrer GNOME Shell" ++ ++#: update.js:174 ++msgid "Restart GNOME Shell" ++msgstr "Redémarrer GNOME Shell" ++ ++#: update.js:174 ++msgid "Restarting GNOME Shell..." ++msgstr "Redémarrage de GNOME Shell..." ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Rien pour l'instant !" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Quand minimiser est sélectionné, un double-clic réduit toutes les fenêtres " ++"de l'application." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Action Maj+Clic" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Montrer les fenêtres" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Réduire la fenêtre" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Lancer une nouvelle instance" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Cycler sur les fenêtres" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Cycler sur les fenêtres + réduire" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Prévisualisation simple / multiple" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Comportement du clic molette." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Action clic molette" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Comportement pour Maj+Clic molette." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Action de Maj+Clic molette" ++ ++#: Settings.ui.h:15 ++msgid "Integrate AppMenu items" ++msgstr "Intégrer les actions du Menu d'applications" ++ ++#: Settings.ui.h:16 ++msgid "Show Details menu item" ++msgstr "Menu Afficher les détails" ++ ++#: Settings.ui.h:17 ++msgid "Highlight focused application" ++msgstr "Surligner l'application active" ++ ++#: Settings.ui.h:18 ++msgid "Icon dominant color" ++msgstr "Couleur d'icône dominante" ++ ++#: Settings.ui.h:19 ++msgid "Custom color" ++msgstr "Couleur personnalisée" ++ ++#: Settings.ui.h:20 ++msgid "Highlight opacity" ++msgstr "Opacité du surlignement" ++ ++#: Settings.ui.h:21 ++msgid "Indicator size (px)" ++msgstr "Taille de l'indicateur (px)" ++ ++#: Settings.ui.h:22 ++msgid "Indicator color - Icon Dominant" ++msgstr "Couleur de l'indicateur - Icône dominante" ++ ++#: Settings.ui.h:23 ++msgid "Indicator color - Override Theme" ++msgstr "Couleur de l'indicateur - Remplacer le thème" ++ ++#: Settings.ui.h:24 ++msgid "1 window open (or ungrouped)" ++msgstr "1 fenêtre ouverte (ou dégroupée)" ++ ++#: Settings.ui.h:25 ++msgid "Apply to all" ++msgstr "Appliquer à tout" ++ ++#: Settings.ui.h:26 ++msgid "2 windows open" ++msgstr "2 fenêtres ouvertes" ++ ++#: Settings.ui.h:27 ++msgid "3 windows open" ++msgstr "3 fenêtres ouvertes" ++ ++#: Settings.ui.h:28 ++msgid "4+ windows open" ++msgstr "4+ fenêtres ouvertes" ++ ++#: Settings.ui.h:29 ++msgid "Use different for unfocused" ++msgstr "Style différent pour les applications inactives" ++ ++#: Settings.ui.h:30 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Taille (px) du texte des titres d'application (défaut: 14)" ++ ++#: Settings.ui.h:31 ++msgid "Font weight of application titles" ++msgstr "Épaisseur de la police du texte des titres d'application" ++ ++#: Settings.ui.h:32 ++msgid "inherit from theme" ++msgstr "hériter du thème" ++ ++#: Settings.ui.h:33 ++msgid "normal" ++msgstr "normale" ++ ++#: Settings.ui.h:34 ++msgid "lighter" ++msgstr "plus légere" ++ ++#: Settings.ui.h:35 ++msgid "bold" ++msgstr "grasse" ++ ++#: Settings.ui.h:36 ++msgid "bolder" ++msgstr "plus grasse" ++ ++#: Settings.ui.h:37 ++msgid "Font color of the application titles" ++msgstr "Couleur du texte des titres d'application" ++ ++#: Settings.ui.h:38 ++msgid "Font color of the minimized application titles" ++msgstr "Couleur du texte des titres d'application de fenêtres minimisées" ++ ++#: Settings.ui.h:39 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Longueur maximum (px) des titres d'application (défaut: 160)" ++ ++#: Settings.ui.h:40 ++msgid "Use a fixed width for the application titles" ++msgstr "Utiliser une largeur fixe pour les titres d'application" ++ ++#: Settings.ui.h:41 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Les titres d'application ont tous la même longueur, même si leur texte est " ++"plus petit que la taille maximum. La valeur maximale de longueur est " ++"utilisée comme longueur fixe." ++ ++#: Settings.ui.h:42 ++msgid "Display running indicators on unfocused applications" ++msgstr "Afficher des indicateurs sur les applications an arrière-plan" ++ ++#: Settings.ui.h:43 ++msgid "Use the favorite icons as application launchers" ++msgstr "Utiliser les applications favorites comme lanceurs" ++ ++#: Settings.ui.h:44 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Ne cacher le panneau que lorsqu'il est au-dessus d'une fenêtre " ++ ++#: Settings.ui.h:45 ++msgid "The panel hides from" ++msgstr "Le panneau se cache de" ++ ++#: Settings.ui.h:46 ++msgid "All windows" ++msgstr "Toutes les fenêtres" ++ ++#: Settings.ui.h:47 ++msgid "Focused windows" ++msgstr "Fenêtres au premier plan" ++ ++#: Settings.ui.h:48 ++msgid "Maximized windows" ++msgstr "Fenêtres maximisées" ++ ++#: Settings.ui.h:49 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Requérir une pression sur le bord de l'écran pour afficher le panneau" ++ ++#: Settings.ui.h:50 ++msgid "Required pressure threshold (px)" ++msgstr "Seuil d'activation (px)" ++ ++#: Settings.ui.h:51 ++msgid "Required pressure timeout (ms)" ++msgstr "Délai d'activation (ms)" ++ ++#: Settings.ui.h:52 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Permettre au panneau d'être affiché en mode plein écran" ++ ++#: Settings.ui.h:53 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Ne cacher que les panneaux secondaires (multi-moniteurs)" ++ ++#: Settings.ui.h:54 ++msgid "e.g. i" ++msgstr "e.g. i" ++ ++#: Settings.ui.h:55 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Raccourci clavier pour révéler et maintenir le panneau" ++ ++#: Settings.ui.h:56 ++msgid "Syntax: , , , " ++msgstr "Syntaxe: , , , " ++ ++#: Settings.ui.h:57 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Durée des animations d'affichage (ms)" ++ ++#: Settings.ui.h:58 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Délai avant le masquage du panneau (ms)" ++ ++#: Settings.ui.h:59 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Délai avant l'activation du masquage intelligent (ms)" ++ ++#: Settings.ui.h:60 ++msgid "Time (ms) before showing (400 is default)" ++msgstr "Temps (ms) avant d'afficher (400 par défaut)" ++ ++#: Settings.ui.h:61 ++msgid "Animation time (ms)" ++msgstr "Durée d'animation (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Temps (ms) avant de cacher (100 par défaut)" ++ ++#: Settings.ui.h:63 ++msgid "Immediate on application icon click" ++msgstr "Immédiat au clic d'application" ++ ++#: Settings.ui.h:64 ++msgid "Middle click on the preview to close the window" ++msgstr "Cliquez avec la molette sur la prévisualisation pour fermer la fenêtre" ++ ++#: Settings.ui.h:65 ++msgid "Window previews preferred size (px)" ++msgstr "Taille des prévisualisations de fenêtres (px)" ++ ++#: Settings.ui.h:66 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Ratio d'aspect des prévisualisations (hauteur)" ++ ++#: Settings.ui.h:67 ++msgid "Window previews padding (px)" ++msgstr "Marge intérieure des prévisualisations (px)" ++ ++#: Settings.ui.h:68 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:69 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:70 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:71 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:72 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:73 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:74 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:75 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:76 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:77 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:78 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:79 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:80 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:81 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:82 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:83 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:84 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:85 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:86 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:87 ++msgid "20" ++msgstr "200" ++ ++#: Settings.ui.h:88 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:89 ++msgid "Fixed" ++msgstr "Fixé" ++ ++#: Settings.ui.h:90 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Ratio d'aspect des prévisualisations (largeur)" ++ ++#: Settings.ui.h:91 ++msgid "Use custom opacity for the previews background" ++msgstr "Opacité personnalisée pour l'arrière plan des prévisualisations" ++ ++#: Settings.ui.h:92 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "Si désactivé, les prévisualisations ont la même opacité que le panneau" ++ ++#: Settings.ui.h:93 ++msgid "Close button and header position" ++msgstr "Bouton de fermeture et position de l'en-tête" ++ ++#: Settings.ui.h:94 ++msgid "Bottom" ++msgstr "Bas" ++ ++#: Settings.ui.h:95 ++msgid "Top" ++msgstr "Haut" ++ ++#: Settings.ui.h:96 ++msgid "Display window preview headers" ++msgstr "Afficher le titre de la fenêtre dans la prévis." ++ ++#: Settings.ui.h:97 ++msgid "Font size (px) of the preview titles" ++msgstr "Taille (px) du texte des prévisualisations" ++ ++#: Settings.ui.h:98 ++msgid "Font weight of the preview titles" ++msgstr "Épaisseur du texte des titres de prévisualisation" ++ ++#: Settings.ui.h:99 ++msgid "Font color of the preview titles" ++msgstr "Couleur du texte des titres de prévisualisation" ++ ++#: Settings.ui.h:100 ++msgid "Enable window peeking" ++msgstr "Activer la vue de fenêtre" ++ ++#: Settings.ui.h:101 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Le survol sur la prévisualisation de la fenêtre, pendant un certain temps, " ++"la met en avant." ++ ++#: Settings.ui.h:102 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Temps d'attente avant activation de la vue fenêtre" ++ ++#: Settings.ui.h:103 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:104 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Temps d'inactivité pendant le survol de la prévisualisation d'une fenêtre " ++"nécessaire pour activer la vue de la fenêtre." ++ ++#: Settings.ui.h:105 ++msgid "Window peeking mode opacity" ++msgstr "Opacité de la vue de fenêtre" ++ ++#: Settings.ui.h:106 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:107 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"Toutes les fenêtres, mis à part celle prévisualisée, ont leur opacité mise à " ++"la même valeur." ++ ++#: Settings.ui.h:108 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Délai entre les évènements de défilement de la souris (ms)" ++ ++#: Settings.ui.h:109 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Utiliser cette valeur pour limiter le nombre d'évènements de défilement de " ++"la souris (ms)" ++ ++#: Settings.ui.h:110 ++msgid "Show popup when changing workspace" ++msgstr "Afficher l'indicateur de changement d'espace de travail" ++ ++#: Settings.ui.h:111 ++msgid "This affects workspace popup when scrolling on the panel only." ++msgstr "" ++"Affecte uniquement l'indicateur de changement d'espace de travail au " ++"défilement de la souris sur le panneau." ++ ++#: Settings.ui.h:112 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:113 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:114 ++msgid "Hotkeys prefix" ++msgstr "Préfixe raccourcis" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Les raccourcis seront soit Super+Numéro soit Super+Alt+Numéro" ++ ++#: Settings.ui.h:116 ++msgid "Never" ++msgstr "Jamais" ++ ++#: Settings.ui.h:117 ++msgid "Show temporarily" ++msgstr "Afficher temporairement" ++ ++#: Settings.ui.h:118 ++msgid "Always visible" ++msgstr "Toujours visible" ++ ++#: Settings.ui.h:119 ++msgid "Number overlay" ++msgstr "Superposition des nombres" ++ ++#: Settings.ui.h:120 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Afficher temporairement les numéros des applications par dessus les icônes " ++"lors de l'utilisation des raccourcis." ++ ++#: Settings.ui.h:121 ++msgid "Hide timeout (ms)" ++msgstr "Délai avant de cacher (ms)" ++ ++#: Settings.ui.h:122 ++msgid "e.g. q" ++msgstr "e.g. q" ++ ++#: Settings.ui.h:123 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Raccourci pour afficher la superposition pendant 2 secondes" ++ ++#: Settings.ui.h:124 ++msgid "Show window previews on hotkey" ++msgstr "Afficher les aperçus des fenêtres lors de l'utilisation d'un raccourci" ++ ++#: Settings.ui.h:125 ++msgid "Show previews when the application have multiple instances" ++msgstr "" ++"Afficher les aperçus lorsque les applications possèdent plusieurs fenêtres" ++ ++#: Settings.ui.h:126 ++msgid "Number row" ++msgstr "Rangée des chiffres" ++ ++#: Settings.ui.h:127 ++msgid "Numeric keypad" ++msgstr "Pavé numérique" ++ ++#: Settings.ui.h:128 ++msgid "Both" ++msgstr "Les deux" ++ ++#: Settings.ui.h:129 ++msgid "Hotkeys are activated with" ++msgstr "Les raccourcis sont activés par" ++ ++#: Settings.ui.h:130 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Sélectionner quelles touches numériques sont utilisées pour activer les " ++"raccourcis" ++ ++#: Settings.ui.h:131 ++msgid "Current Show Applications icon" ++msgstr "Icône Afficher les Applications actuelle" ++ ++#: Settings.ui.h:132 ++msgid "Select a Show Applications image icon" ++msgstr "Sélectionner une icône Afficher les Applications" ++ ++#: Settings.ui.h:133 ++msgid "Custom Show Applications image icon" ++msgstr "Icône d'affichage des applications personnalisée" ++ ++#: Settings.ui.h:134 ++msgid "Show Applications icon side padding (px)" ++msgstr "Marge interne du bouton \"Afficher les Applications\"" ++ ++#: Settings.ui.h:135 ++msgid "Override escape key and return to desktop" ++msgstr "" ++"Remplacer l'action de la touche d'échappement et retourner sur le bureau" ++ ++#: Settings.ui.h:136 ++msgid "Animate Show Applications." ++msgstr "Animer Afficher les applications." ++ ++#: Settings.ui.h:137 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Révéler le bureau lors du survol du bouton \"Afficher le Bureau\"" ++ ++#: Settings.ui.h:138 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Délai avant affichage du bureau (ms)" ++ ++#: Settings.ui.h:139 ++msgid "Fade duration (ms)" ++msgstr "Durée du fondu (ms)" ++ ++#: Settings.ui.h:140 ++msgid "The panel background opacity is affected by" ++msgstr "L'opacité de l'arrière-plan du panneau est affectée par" ++ ++#: Settings.ui.h:141 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Changer l'opacité lorsqu'une fenêtre est plus proche que (px)" ++ ++#: Settings.ui.h:143 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Changer l'opacité à (%)" ++ ++#: Settings.ui.h:144 ++msgid "Opacity change animation duration (ms)" ++msgstr "Durée de l'animation de changement d'opacité (ms)" ++ ++#: Settings.ui.h:145 ++msgid "Display the main panel on" ++msgstr "Afficher le panneau principal sur" ++ ++#: Settings.ui.h:146 ++msgid "Display panels on all monitors" ++msgstr "Afficher le panneau principal sur tous les écrans" ++ ++#: Settings.ui.h:147 ++msgid "Panel Intellihide" ++msgstr "Masquage intelligent du panneau" ++ ++#: Settings.ui.h:148 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Afficher/Cacher le panneau selon les préférences" ++ ++#: Settings.ui.h:149 ++msgid "Order and positions on monitor" ++msgstr "Ordre et positions de l'écran" ++ ++#: Settings.ui.h:150 ++msgid "Apply changes to all monitors" ++msgstr "Appliquer les changements sur tous les écrans" ++ ++#: Settings.ui.h:151 ++msgid "Panel screen position" ++msgstr "Position du panneau" ++ ++#: Settings.ui.h:152 ++msgid "Left" ++msgstr "Gauche" ++ ++#: Settings.ui.h:153 ++msgid "Right" ++msgstr "Droit" ++ ++#: Settings.ui.h:154 ++msgid "Position" ++msgstr "Position" ++ ++#: Settings.ui.h:155 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Taille du panneau\n" ++"(la valeur par défaut est 48)" ++ ++#: Settings.ui.h:157 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Marge ext. de l'icône d'application\n" ++"(la valeur par défaut est 8)" ++ ++#: Settings.ui.h:159 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Marge int. de l'icône d'application\n" ++"(la valeur par défaut est 4)" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator position" ++msgstr "Position de l'indicateur d'activité" ++ ++#: Settings.ui.h:162 ++msgid "Running indicator style (Focused app)" ++msgstr "Style de l'indicateur d'activité (Application active)" ++ ++#: Settings.ui.h:163 ++msgid "Dots" ++msgstr "Points" ++ ++#: Settings.ui.h:164 ++msgid "Squares" ++msgstr "Carrés" ++ ++#: Settings.ui.h:165 ++msgid "Dashes" ++msgstr "Traits" ++ ++#: Settings.ui.h:166 ++msgid "Segmented" ++msgstr "Segmenté" ++ ++#: Settings.ui.h:167 ++msgid "Solid" ++msgstr "Solide" ++ ++#: Settings.ui.h:168 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:169 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:170 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Style de l'indicateur d'activité (Applications inactives)" ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background color " ++msgstr "Remplacer la couleur de fond du thème du panneau " ++ ++#: Settings.ui.h:172 ++msgid "Override panel theme background opacity" ++msgstr "Remplacer l'opacité du thème du panneau" ++ ++#: Settings.ui.h:174 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Opacité du fond du panneau" ++ ++#: Settings.ui.h:175 ++msgid "Dynamic background opacity" ++msgstr "Opacité de fond dynamique" ++ ++#: Settings.ui.h:176 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Changer l'opacité lorsqu'une fenêtre s'approche du panneau" ++ ++#: Settings.ui.h:177 ++msgid "Override panel theme gradient " ++msgstr "Remplacer le gradient du thème du panneau " ++ ++#: Settings.ui.h:179 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Couleur et opacité (%) du haut du gradient" ++ ++#: Settings.ui.h:181 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Couleur et opacité (%) du bas du gradient" ++ ++#: Settings.ui.h:182 ++msgid "Style" ++msgstr "Style" ++ ++#: Settings.ui.h:183 ++msgid "Show favorite applications" ++msgstr "Afficher les applications favorites" ++ ++#: Settings.ui.h:184 ++msgid "Show running applications" ++msgstr "Afficher les applications ouvertes" ++ ++#: Settings.ui.h:185 ++msgid "Show favorite applications on secondary panels" ++msgstr "Afficher les applications favorites sur les panneaux secondaires" ++ ++#: Settings.ui.h:186 ++msgid "Show AppMenu button" ++msgstr "Afficher le bouton Menu d'Applications" ++ ++#: Settings.ui.h:187 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Barre supérieure > Afficher le menu de l'application doit être activé dans " ++"Ajustements" ++ ++#: Settings.ui.h:188 ++msgid "Show window previews on hover" ++msgstr "Afficher les aperçus des fenêtres lors du survol" ++ ++#: Settings.ui.h:189 ++msgid "Show tooltip on hover" ++msgstr "Afficher les bulles d'info. lors du survol" ++ ++#: Settings.ui.h:190 ++msgid "Isolate Workspaces" ++msgstr "Isoler les espaces de travail" ++ ++#: Settings.ui.h:191 ++msgid "Isolate monitors" ++msgstr "Isoler les écrans" ++ ++#: Settings.ui.h:192 ++msgid "Ungroup applications" ++msgstr "Dégrouper les applications" ++ ++#: Settings.ui.h:193 ++msgid "Behavior" ++msgstr "Comportement" ++ ++#: Settings.ui.h:194 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Comportement lors du clic sur l'icône d'une application lancée." ++ ++#: Settings.ui.h:195 ++msgid "Click action" ++msgstr "Action du clic" ++ ++#: Settings.ui.h:196 ++msgid "Toggle windows" ++msgstr "Basculer les fenêtres" ++ ++#: Settings.ui.h:197 ++msgid "Scroll panel action" ++msgstr "Action du défilement de la souris sur le panneau" ++ ++#: Settings.ui.h:198 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Comportement lors du défilement de la souris sur le panneau" ++ ++#: Settings.ui.h:199 ++msgid "Scroll icon action" ++msgstr "Action du défilement de la souris sur une application" ++ ++#: Settings.ui.h:200 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Comportement lors du défilement de la souris sur une application" ++ ++#: Settings.ui.h:201 ++msgid "Do nothing" ++msgstr "Ne rien faire" ++ ++#: Settings.ui.h:202 ++msgid "Switch workspace" ++msgstr "Défiler les espaces de travail" ++ ++#: Settings.ui.h:203 ++msgid "Cycle windows" ++msgstr "Défiler les fenêtres" ++ ++#: Settings.ui.h:204 ++msgid "Change volume" ++msgstr "Changer le volume" ++ ++#: Settings.ui.h:205 ++msgid "Same as panel" ++msgstr "Comme le panneau" ++ ++#: Settings.ui.h:206 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Activer Super+(0-9) comme raccourcis pour lancer les applications. Maj et " ++"Ctrl peuvent aussi être utilisés." ++ ++#: Settings.ui.h:207 ++msgid "Use hotkeys to activate apps" ++msgstr "Utiliser des raccourcis pour lancer les applications" ++ ++#: Settings.ui.h:208 ++msgid "Action" ++msgstr "Action" ++ ++#: Settings.ui.h:209 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Taille de la police\n" ++"(0 = par défaut)" ++ ++#: Settings.ui.h:211 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Taille de la police de la zone de gauche\n" ++"(0 = par défaut)" ++ ++#: Settings.ui.h:213 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Marge des éléments de la barre d'état\n" ++"(-1 = par défaut)" ++ ++#: Settings.ui.h:215 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Marge des icônes de statut\n" ++"(-1 = par défaut)" ++ ++#: Settings.ui.h:217 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Marge de la zone de gauche\n" ++"(-1 = par défaut)" ++ ++#: Settings.ui.h:219 ++msgid "Animate switching applications" ++msgstr "Animer le changement d'application" ++ ++#: Settings.ui.h:220 ++msgid "Animate launching new windows" ++msgstr "Animer le lancement de nouvelles fenêtres" ++ ++#: Settings.ui.h:221 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Garder le lanceur d'origine de gnome-shell (activités)" ++ ++#: Settings.ui.h:222 ++msgid "Force Activities hot corner on primary monitor" ++msgstr "Forcer le coin actif des Activités sur l'écran principal" ++ ++#: Settings.ui.h:223 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "Activer les menus du panneau seulement au clic" ++ ++#: Settings.ui.h:224 ++msgid "Keep original gnome-shell top panel" ++msgstr "Garder le panneau d'origine de gnome-shell" ++ ++#: Settings.ui.h:225 ++msgid "App icon secondary (right-click) menu" ++msgstr "Menu secondaire de l'application (clic droit)" ++ ++#: Settings.ui.h:227 ++msgid "Fine-Tune" ++msgstr "Personnalisation" ++ ++#: Settings.ui.h:228 ++msgid "version: " ++msgstr "version: " ++ ++#: Settings.ui.h:229 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:230 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Utiliser les boutons ci-dessous pour créer un fichier de paramètres à partir " ++"de vos préférences actuelles qui pourra être importé sur une autre machine." ++ ++#: Settings.ui.h:231 ++msgid "Export and import settings" ++msgstr "Import et export de paramètres" ++ ++#: Settings.ui.h:232 ++msgid "Export to file" ++msgstr "Exporter vers un fichier" ++ ++#: Settings.ui.h:233 ++msgid "Import from file" ++msgstr "Importer à partir d'un fichier" ++ ++#: Settings.ui.h:234 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Ceci vous permet de mettre l'extension à jour directement depuis GitHub" ++ ++#: Settings.ui.h:235 ++msgid "Updates" ++msgstr "Mises à jour" ++ ++#: Settings.ui.h:236 ++msgid "Periodically check for updates" ++msgstr "Vérifier périodiquement les mises à jour" ++ ++#: Settings.ui.h:237 ++msgid "Check now" ++msgstr "Vérifier maintenant" ++ ++#: Settings.ui.h:238 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Soyez avisé, ces versions " ++"officielles de Dash to Panel n'ont peut-être pas encore été approuvées sur " ++"extensions.gnome.org! En savoir plus" ++ ++#: Settings.ui.h:239 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Ce programme est fourni SANS AUCUNE GARANTIE.\n" ++"Pour plus de détails, visitez la Licence publique générale GNU, version 2 ou " ++"ultérieure" ++ ++#: Settings.ui.h:241 ++msgid "About" ++msgstr "À propos" ++ + #~ msgid "Attach modal dialog to the parent window" + #~ msgstr "Attacher les boîtes de dialogue modales à leur fenêtre parente" + +@@ -527,3 +1775,145 @@ msgstr "Montrer la corbeille sur le bureau." + + #~ msgid "Ok" + #~ msgstr "Valider" ++ ++#~ msgid "Top, with plugin icons collapsed to bottom" ++#~ msgstr "En haut, et placer les icônes de plugins au bas" ++ ++#~ msgid "Left, with plugin icons collapsed to right" ++#~ msgstr "À gauche, et placer les icônes de plugins sur la droite" ++ ++#~ msgid "Top, with fixed center plugin icons" ++#~ msgstr "En haut, et fixer les icônes de plugins au centre" ++ ++#~ msgid "Left, with fixed center plugin icons" ++#~ msgstr "À gauche, et fixer les icônes de plugins au centre" ++ ++#~ msgid "Top, with floating center plugin icons" ++#~ msgstr "En haut, et laisser flotter les icônes de plugins au centre" ++ ++#~ msgid "Left, with floating center plugin icons" ++#~ msgstr "À gauche, et laisser flotter les icônes de plugins au centre" ++ ++#~ msgid "Center, fixed in middle of monitor" ++#~ msgstr "Centrer, et fixer au milieu de l'écran" ++ ++#~ msgid "Center, floating between top and bottom elements" ++#~ msgstr "Centrer, et laisser flotter entre les éléments du haut et du bas" ++ ++#~ msgid "Center, floating between left and right elements" ++#~ msgstr "Centrer, et laisser flotter entre les éléments à gauche et à droite" ++ ++#~ msgid "Top of plugin icons" ++#~ msgstr "En haut des icônes de plugins" ++ ++#~ msgid "Left of plugin icons" ++#~ msgstr "À gauche des icônes de plugins" ++ ++#~ msgid "Bottom of plugin icons" ++#~ msgstr "En bas des icônes de plugins" ++ ++#~ msgid "Right of plugin icons" ++#~ msgstr "À droite des icônes de plugins" ++ ++#~ msgid "Top of system indicators" ++#~ msgstr "En haut du menu système" ++ ++#~ msgid "Left of system indicators" ++#~ msgstr "À gauche du menu système" ++ ++#~ msgid "Bottom of system indicators" ++#~ msgstr "En bas du menu système" ++ ++#~ msgid "Right of system indicators" ++#~ msgstr "À droite du menu système" ++ ++#~ msgid "Left of taskbar" ++#~ msgstr "À gauche de la barre des tâches" ++ ++#~ msgid "Bottom of taskbar" ++#~ msgstr "En bas de la barre des tâches" ++ ++#~ msgid "Right of taskbar" ++#~ msgstr "À droite de la barre des tâches" ++ ++#~ msgid "Multi-monitors options" ++#~ msgstr "Options multi-écran" ++ ++#~ msgid "Event logs" ++#~ msgstr "Journaux d'évènements" ++ ++#~ msgid "System" ++#~ msgstr "Système" ++ ++#~ msgid "Device Management" ++#~ msgstr "Gestionnaire de périphériques" ++ ++#~ msgid "Disk Management" ++#~ msgstr "Gestionnaire de disques" ++ ++#~ msgid "Terminal" ++#~ msgstr "Terminal" ++ ++#~ msgid "Files" ++#~ msgstr "Fichiers" ++ ++#~ msgid "Extensions" ++#~ msgstr "Extensions" ++ ++#~ msgid "Display favorite applications on all monitors" ++#~ msgstr "Afficher les applications favorites sur tous les écrans" ++ ++#~ msgid "Display the clock on all monitors" ++#~ msgstr "Afficher l'horloge sur tous les écrans" ++ ++#~ msgid "Display the status menu on all monitors" ++#~ msgstr "Afficher le menu système sur tous les écrans" ++ ++#~ msgid "Taskbar position" ++#~ msgstr "Position de la barre des tâches" ++ ++#~ msgid "Clock location" ++#~ msgstr "Position de l'horloge" ++ ++#~ msgid "Show Applications icon" ++#~ msgstr "Afficher l'icône Applications" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Couleur de surlignement" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Délai de l'aperçu lorsqu'on quitte l'icône (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Si trop bas, l'aperçu des fenêtres des applications actives peut sembler " ++#~ "se fermer trop vite quand on essaie de cliquer sur l'aperçu. Si trop " ++#~ "haut, l'aperçu peut rester trop longtemps quand on passe à une icône " ++#~ "adjacente." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Cliquez avec la molette pour fermer la fenêtre" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Largeur des aperçus des fenêtres lors du survol (px)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Hauteur des aperçus des fenêtres lors du survol (px)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Marge des prévisualisations (px)" ++ ++#~ msgid "Natural" ++#~ msgstr "Naturelle" ++ ++#~ msgid "Left side of panel" ++#~ msgstr "Côté gauche de la barre" ++ ++#~ msgid "Centered in content" ++#~ msgstr "Centré sur le contenu" ++ ++#~ msgid "Github" ++#~ msgstr "GitHub" +diff --git a/po/gl.po b/po/gl.po +index 815d6f0f..31ca9d52 100644 +--- a/po/gl.po ++++ b/po/gl.po +@@ -357,6 +357,1306 @@ msgstr "Nome" + msgid "Workspace %d" + msgstr "Espazos de traballo %d" + ++#: Settings.ui.h:145 ++#, fuzzy ++msgid "Left" ++msgstr "" ++"#-#-#-#-# gl.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Esquerda\n" ++"#-#-#-#-# gl.po (dash-to-panel) #-#-#-#-#\n" ++"Á esquerda" ++ ++#: Settings.ui.h:146 ++#, fuzzy ++msgid "Right" ++msgstr "" ++"#-#-#-#-# gl.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Dereita\n" ++"#-#-#-#-# gl.po (dash-to-panel) #-#-#-#-#\n" ++"Á dereita" ++ ++#: appIcons.js:1429 ++#, fuzzy ++msgid "New Window" ++msgstr "" ++"#-#-#-#-# gl.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Nova xanela\n" ++"#-#-#-#-# gl.po (dash-to-panel) #-#-#-#-#\n" ++"Xanela nova" ++ ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Arriba, coas iconas contraídas" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Á esquerda, coas iconas contraídas á dereita" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Arriba, coas iconas fixas centradas" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Á esquerda, coas iconas fixas centradas" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Arriba, coas iconas flotantes centradas" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Á esquerda, coas iconas flotantes centradas" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Centrado, fixo no medio do monitor" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Centrado, flotando entre os elementos superiores e inferiores" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Centrado, flotando entre os elementos da esquerda e dereita" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Enriba das iconas" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "Á esquerda das iconas" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Embaixo das iconas" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "Á dereita das iconas" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Enriba dos indicadores do sistema" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "Á esquerda dos indicadores do sistema" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Embaixo dos indicadores do sistema" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "Á dereita dos indicadores do sistema" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Enriba da barra de tarefas" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "Á esquerda da barra de tarefas" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Embaixo da barra de tareas" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "Á dereita da barra de tareas" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Alto do botón Mostrar Escritorio (px)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Ancho do botón Mostrar Escritorio (px)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Opcións do indicador de execución" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1084 prefs.js:1331 prefs.js:1415 prefs.js:1480 ++#: prefs.js:1516 prefs.js:1613 prefs.js:1647 prefs.js:1689 ++msgid "Reset to defaults" ++msgstr "Restabelecer os valores predeterminados" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Por defecto (Monitor principal)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Monitor" ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Opcións de multimonitores" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Opcións de opacidade dinámica" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Opcións de «Intellihide»" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Mostrar as opciones de aplicación" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Mostrar o Escritorio" ++ ++#: prefs.js:1077 ++msgid "Window preview options" ++msgstr "Opcións de vista rápida de xanelas" ++ ++#: prefs.js:1324 ++msgid "Ungrouped application options" ++msgstr "Opcións de xanelas non combinadas" ++ ++#: prefs.js:1408 ++msgid "Customize middle-click behavior" ++msgstr "Personalizar comportamento do botón central" ++ ++#: prefs.js:1473 ++msgid "Customize panel scroll behavior" ++msgstr "Personalizar comportamento do desplazamento do panel" ++ ++#: prefs.js:1509 ++msgid "Customize icon scroll behavior" ++msgstr "Personalizar comportamento do desplazamento das iconas" ++ ++#: prefs.js:1606 ++msgid "Advanced hotkeys options" ++msgstr "Opcións avanzadas de atallos de teclado" ++ ++#: prefs.js:1640 ++msgid "Secondary Menu Options" ++msgstr "Opcións do menú secundario" ++ ++#: prefs.js:1682 Settings.ui.h:226 ++msgid "Advanced Options" ++msgstr "Opcións avanzadas" ++ ++#: prefs.js:1774 ++msgid "Export settings" ++msgstr "Exportar configuracións" ++ ++#: prefs.js:1791 ++msgid "Import settings" ++msgstr "Importar configuracións" ++ ++#: appIcons.js:1411 ++msgid "Show Details" ++msgstr "Mostrar detalles" ++ ++#: appIcons.js:1429 appIcons.js:1489 appIcons.js:1491 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Saír" ++ ++#: appIcons.js:1491 ++msgid "Windows" ++msgstr "Xanelas" ++ ++#: appIcons.js:1745 ++msgid "Power options" ++msgstr "Opcións de enerxía" ++ ++#: appIcons.js:1750 ++msgid "Event logs" ++msgstr "Rexistros do sistema" ++ ++#: appIcons.js:1755 ++msgid "System" ++msgstr "Sistema" ++ ++#: appIcons.js:1760 ++msgid "Device Management" ++msgstr "Xestión de dispositivo" ++ ++#: appIcons.js:1765 ++msgid "Disk Management" ++msgstr "Xestión de discos" ++ ++#: appIcons.js:1773 ++msgid "Terminal" ++msgstr "Terminal" ++ ++#: appIcons.js:1778 ++msgid "System monitor" ++msgstr "Monitor do sistema" ++ ++#: appIcons.js:1783 ++msgid "Files" ++msgstr "Ficheiros" ++ ++#: appIcons.js:1788 ++msgid "Extensions" ++msgstr "Extensións" ++ ++#: appIcons.js:1793 ++msgid "Settings" ++msgstr "Preferencias" ++ ++#: appIcons.js:1800 ++msgid "Unlock taskbar" ++msgstr "Desbloquear barra de tarefas" ++ ++#: appIcons.js:1800 ++msgid "Lock taskbar" ++msgstr "Bloquear barra de tarefas" ++ ++#: appIcons.js:1805 ++msgid "Dash to Panel Settings" ++msgstr "Opcións de Dash to Panel" ++ ++#: appIcons.js:1818 ++msgid "Restore Windows" ++msgstr "Restaurar xanelas" ++ ++#: appIcons.js:1818 ++msgid "Show Desktop" ++msgstr "Mostrar o Escritorio" ++ ++#: update.js:48 ++msgid "Unavailable when installed from extensions.gnome.org" ++msgstr "Non dispoñíbel cando se instala desde extensions.gnome.org" ++ ++#: update.js:62 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "A versión %s (%s) está dispoñíbel" ++ ++#: update.js:63 ++msgid "Details" ++msgstr "Mostrar detalles" ++ ++#: update.js:64 ++msgid "Update" ++msgstr "Actualizar" ++ ++#: update.js:67 ++msgid "Already up to date" ++msgstr "Xa está actualizado" ++ ++#: update.js:75 ++msgid "Error: " ++msgstr "Erro: " ++ ++#: update.js:168 ++msgid "Update successful, please log out/in" ++msgstr "Actualización correcta, por favor, peche e inicie sesión" ++ ++#: update.js:169 ++msgid "Log out" ++msgstr "Pechar sesión" ++ ++#: update.js:173 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Actualización correcta, por favor, restaure GNOME Shell" ++ ++#: update.js:174 ++msgid "Restart GNOME Shell" ++msgstr "Reiniciar GNOME Shell" ++ ++#: update.js:174 ++msgid "Restarting GNOME Shell..." ++msgstr "Reiniciando GNOME Shel..." ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Aínda nada!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Cuando está a minimizar, doble pulsación minimiza todas as xanelas da " ++"aplicación." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Acción de Maiúsculas+Click" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Elevar xanelas" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Minimizar xanelas" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Lanzar unha nova xanela" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Alternar entre xanelas" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Alternar xanelas e minimizar" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Trocar entre simple e vista rápida múltiple" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Comportamento do botón central" ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Acción do botón central" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Comportamento para Maiúsculas+Botón-Central" ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Acción de Maiúsculas+Botón-Central" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Illar os espazos de traballo" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Mostrar aplicacións favoritas en todos os espazos de traballo" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Mostrar reloxo en todos os espazos de traballo" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Mostrar o menú de estado en todos os espazos de traballo" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Integrar os elementos do Menú de aplicación" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Mostrar detalles do menú de elementos" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Realzar a aplicación activa" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Color da icona predominante" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Cor personalizado" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Opacidade de realzado" ++ ++#: Settings.ui.h:25 ++msgid "Indicator size (px)" ++msgstr "Tamaño do indicador (px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Cor do indicador - Predominar a icona" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Color do indicador - Predominar sobre o tema" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 xanela aberta (ou non combinada)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Aplicar a todo" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 xanelas abertas" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 xanelas abertas" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4+ xanelas abertas" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Usar diferente para desenfoque" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Tamaño da fonte (px) para os títulos de aplicación (14 por defecto)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Tamaño da fonte para os títulos de aplicación" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "herdado do tema" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normal" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "máis fino" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "en negriña" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "máis en negriña" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Cor de letra dos títulos de aplicación" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Ancho máximo (px) dos títulos de aplicación (160 por defecto)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Usar ancho fixo para os títulos de aplicación" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Todos os títulos de aplicación teñen o mesmo ancho, aínda se o seu texto é " ++"máis curto que o ancho máximo. O ancho máximo é usado como valor fixo." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Estilo dos indicadores de execución (aplicación non enfocada)" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Usar as iconas favoritas como lanzadores de aplicación" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Esconder o panel sólo cando é obstruido por xanelas" ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "O panel escóndese de" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Todas as xanelas" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Xanelas enfocadas" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Xanelas maximizadas" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Requirir presión no bordo da pantalla para mostrar o panel" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Presión mínima requirida (px)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Tempo de activación por presión (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "En modo pantalla completa, permitir que o panel sexa mostrado" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Ocultar só os paneis secundarios (require opción multi-monitor)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "p.ex. i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Atallos do teclado para mostrar e manter o panel" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Sintaxe: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Duración de ocultar e mostrar animacións (ms)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Tempo antes de ocultar o panel (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Tempo antes de activar o panel intelixente (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Tempo (ms) antes de mostrar (100 por defecto)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Tempo da animación (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Tempo (ms) antes de ocultar (100 por defecto)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Pulsación inmediata en icona de aplicación" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Usar o botón central na vista rápida para cerrar a xanela" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Tamaño por defecto das vistas rápidas (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Altura da vista rápida de xanelas" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Recheo (px) da vista rápida de xanelas" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Fixa" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Anchura da vista rápida de xanelas" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Usar opacidade personalizada para o fondo das vistas rápidas" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Se está desactivado, o fondo dos vistas rápidas teñen a mesma opacidade que " ++"a do panel" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Botón de apagado e posición dos títulos" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Abaixo" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Enriba" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Mostrar os títulos das xanelas nas vistas rápidas" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Tamaño de letra (px) dos títulos de aplicación (14 por defecto)" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Color de letra dos títulos de aplicación" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Color de letra dos títulos de aplicación" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Activar ollada rápida de xanela" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Al desprazxar o rato sobre unha vista rápida de xanela, a xanela reálzase." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Tempo para activar o modo de ollada rápida (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Tempo de inactividade ao desprazar o rato sobre unha vista rápida de xanela " ++"para activar o modo de ollada rápida." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Opacidad do modo de ollada rápida" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "Todas as xanelas excepto a resaltada ten a mesma opacidade fixa." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Atraso entre eventos de desprazamento do rato (ms)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Usar este valor para limitar o número de eventos de desprazamento capturados " ++"do rato" ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Prefixo de atallo de teclado" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Os atallos serán Super+Núm. ou Super+Alt+Núm." ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Nunca" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Mostrar temporalmente" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Sempre visíbel" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Número de aplicación" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Ao usar atallos, mostrar momentaneamente o número de aplicación sobre as " ++"iconas." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Tempo de ocultación (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "p.e. q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Atallo para mostrar o número de aplicación por 2 segundos" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Mostrar vista rápida de xanelas ao pasar co rato" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Mostrar vistas previas cando a aplicación ten múltiples instancias" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Fila numérica" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Teclado numérico" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Ambos" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Usar atallos de teclado para activar aplicacións" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Selecciona qué teclas numéricas se usan para activar os atallos de teclado" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Icona actual de Mostrar aplicacións" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Seleccionar icona personalizada para Mostrar aplicacións" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Imaxe da icona personalizada de Mostrar aplicacións" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Recheo lateral da icona de Mostrar aplicacións (px)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "" ++"Mostrar escritorio ao colocar pasar por enriba do botón Mostrar Escritorio" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Tempo antes de mostrar o escritorio (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Duración de esvaecemento (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "A opacidade do fondo do panel está afectada por" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Cambiar a opacidade cando unha xanela se aproxima (px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Cambiar a opacidade a (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Duración das animacións de cambio de opacidade (ms)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Posición do panel na pantalla" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Posición da barra de tarefas" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Posición do reloxo" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Mostrar o panel principal en" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Mostrar os paneles en todos os espazos de traballo" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Ocultación intelixente do panel" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Ocultar e mostrar o panel de acordo coas preferencias" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Posición" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Tamaño do panel\n" ++"(48 por defecto)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Marxe das iconas\n" ++"(8 por defecto)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Recheo das iconas\n" ++"(4 por defecto)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Posición dos indicadores de execución" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Estilo dos indicadores de execución (aplicación enfocada)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Puntos" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Cadrados" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Guións" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Segmentado" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Sólido" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Estilo dos indicadores de execución (aplicación non enfocada)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Cambiar a cor de fondo do tema do panel " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Cambiar a opacidade de fondo do tema do panel" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Opacidade do fondo do panel (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Opacidade dinámica do fondo" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Cambiar a opacidade cando unha xanela se aproxima ao panel" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Cambiar o gradiente do tema do panel" ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Color e opacidade do gradiente superior (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Color e opacidadd do gradiente inferior (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Estilo" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Mostrar aplicacións favoritas" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Mostrar aplicacións en execución" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Mostrar a icona de Aplicacións" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Animar Mostrar Aplicacións" ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Mostrar o botón Actividades" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Mostrar o botón Escritorio" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Mostrar o botón Menú de Aplicación" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Barra superior > Mostrar menú de aplicación habilitado en Ferramenta de " ++"retoques." ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Mostrar vista rápida de xanelas ao pasar co rató" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Mostrar barra de ferramentas al pasar co rato" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Illar os espazos de traballo" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Desagrupar aplicacións" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Comportamento" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Comportamento ao pulsar a icona dunha aplicación en execución" ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Acción de pulsación" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Trocar xanelas" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Acción do panel de desprazamento" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Comportamento cando o rato se desplaza no panel" ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Acción ao desplazar iconas" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Comportamento cando o rató se desplaza sobre a icona dunha aplicación" ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Non facer nada" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Cambiar espazo de traballo" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Trocar entre xanelas" ++ ++#: Settings.ui.h:205 ++msgid "Change volume" ++msgstr "Cambiar o volume" ++ ++#: Settings.ui.h:206 ++msgid "Same as panel" ++msgstr "A mesma que o panel" ++ ++#: Settings.ui.h:207 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Activar Super+(0-9) como atallos para activar aplicacións. Tamén pode ser " ++"usado xunto con Maiús. e Ctrl." ++ ++#: Settings.ui.h:208 ++msgid "Use hotkeys to activate apps" ++msgstr "Usar atallos de teclado para activar aplicacións" ++ ++#: Settings.ui.h:209 ++msgid "Action" ++msgstr "Acción" ++ ++#: Settings.ui.h:210 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tamaño do tipo de letra na bandexa do sistema\n" ++"(0 = predeterminado)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tamaño do tipo de letra na zona esquerda\n" ++"(0 = predeterminado)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Separación na bandexa do sistema\n" ++"(-1 = predeterminado)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Separación das iconas de estado\n" ++"(-1 = predeterminado)" ++ ++#: Settings.ui.h:218 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Separación na zona esquerda\n" ++"(-1 = predeterminado)" ++ ++#: Settings.ui.h:220 ++msgid "Animate switching applications" ++msgstr "Animar ao cambiar de aplicación" ++ ++#: Settings.ui.h:221 ++msgid "Animate launching new windows" ++msgstr "Animar ao abrir novas xanelas" ++ ++#: Settings.ui.h:222 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Conservar o dash original de gnome-shell (vista principal)" ++ ++#: Settings.ui.h:223 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "Activar os botóns do menú do panel (p.ex. menú de frecha) só ao pulsar" ++ ++#: Settings.ui.h:224 ++msgid "Force Activities hot corner on primary monitor" ++msgstr "Forzar as actividades da esquina 'quente' no monitor principal" ++ ++#: Settings.ui.h:225 ++msgid "App icon secondary (right-click) menu" ++msgstr "Menú secundario (clic dereito) de aplicación" ++ ++#: Settings.ui.h:227 ++msgid "Fine-Tune" ++msgstr "Retoques" ++ ++#: Settings.ui.h:228 ++msgid "version: " ++msgstr "versión: " ++ ++#: Settings.ui.h:229 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:230 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Usar os botóns de abaixo para crear o fichero de configuración coas súas " ++"preferencias actuais para poder ser importadas de outra máquina." ++ ++#: Settings.ui.h:231 ++msgid "Export and import settings" ++msgstr "Exportar e importar configuración" ++ ++#: Settings.ui.h:232 ++msgid "Export to file" ++msgstr "Exportar a un ficheiro" ++ ++#: Settings.ui.h:233 ++msgid "Import from file" ++msgstr "Importar dun ficheiro" ++ ++#: Settings.ui.h:234 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Isto permítelle actualizar a extensión directamente do repositorio GitHub" ++ ++#: Settings.ui.h:235 ++msgid "Updates" ++msgstr "Actualizacións" ++ ++#: Settings.ui.h:236 ++msgid "Periodically check for updates" ++msgstr "Comprobar periódicamente actualizacións" ++ ++#: Settings.ui.h:237 ++msgid "Check now" ++msgstr "Comprobar agora" ++ ++#: Settings.ui.h:238 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"¡Sé consciente de que estas versións " ++"oficiais de 'Dash to Panel' poderían non estar todavía revisadas en " ++"extensions.gnome.org! Ler máis" ++ ++#: Settings.ui.h:239 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Este programa ven SEN NINGUNHA GARANTÍA.\n" ++"Consulte a Licencia Pública General de GNU, versión 2 ou posterior para obtener " ++"máis detalles." ++ ++#: Settings.ui.h:241 ++msgid "About" ++msgstr "Acerca de" ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -393,12 +1693,6 @@ msgstr "Espazos de traballo %d" + #~ msgid "Normal" + #~ msgstr "Normal" + +-#~ msgid "Left" +-#~ msgstr "Esquerda" +- +-#~ msgid "Right" +-#~ msgstr "Dereita" +- + #~ msgid "Upside-down" + #~ msgstr "Co de arriba cara abaixo" + +@@ -435,9 +1729,6 @@ msgstr "Espazos de traballo %d" + #~ msgid "Drag here to add favorites" + #~ msgstr "Arrastre aquí para engadir aos favoritos" + +-#~ msgid "New Window" +-#~ msgstr "Nova xanela" +- + #~ msgid "Quit Application" + #~ msgstr "Saír do aplicativo" + +diff --git a/po/hu.po b/po/hu.po +index 06352708..f9db0948 100644 +--- a/po/hu.po ++++ b/po/hu.po +@@ -468,7 +468,7 @@ msgstr "Háttér megváltoztatása…" + msgid "Display Settings" + msgstr "Megjelenítés beállításai" + +-#: desktopGrid.js:335 ++#: desktopGrid.js:335 appIcons.js:1726 + msgid "Settings" + msgstr "Beállítások" + +@@ -551,3 +551,1275 @@ msgstr "Kuka ikon megjelenítése" + #: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 + msgid "Show the trash icon in the desktop." + msgstr "A kuka ikon megjelenítése az asztalon." ++ ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Fent, a bővítményikonokkal lent összecsukva" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Balra, a bővítményikonokkal jobbra összecsukva" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Fent, középen rögzített bővítményikonokkal" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Balra, középen rögzített bővítményikonokkal" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Fent, középen lebegő bővítményikonokkal" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Balra, középen lebegő bővítményikonokkal" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Középen, a kijelző közepén rögzítve" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Középen, a fenti és lenti elemek között lebegve" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Középen, a bal és jobb oldali elemek között lebegve" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "A bővítményikonok fölött" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "A bővítményikonoktól balra" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "A bővítményikonok alatt" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "A bővítményikonoktól jobbra" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "A rendszerjelzők fölött" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "A rendszerjelzőktől balra" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "A rendszerjelzők alatt" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "A rendszerjelzőktől jobbra" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "A feladatsáv fölött" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "A feladatsávtól balra" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "A feladatsáv alatt" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "A feladatsávtól jobbra" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "„Asztal megjelenítése” gomb magassága (képpont)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "„Asztal megjelenítése” gomb szélessége (képpont)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Futásjelző beállításai" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "Visszaállítás az alapértékekre" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Default (Elsődleges kijelző)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Kijelző" ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Többkijelzős beállítások" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Dinamikus átlátszatlansági beállítások" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Intelligens elrejtés beállításai" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "„Alkalmazások megjelenítése” ikon beállításai" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "„Asztal megjelenítése” gomb beállításai" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "Ablakelőnézet beállításai" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "Nem csoportosított alkalmazás beállításai" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "Középső kattintás viselkedésének személyre szabása" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "Panel görgetési viselkedésének személyre szabása" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "Ikon görgetési viselkedésének személyre szabása" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "Speciális gyorsbillentyű-beállítások" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "Másodlagos menü beállítások" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "Speciális beállítások" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "Beállítások exportálása" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "Beállítások importálása" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "Részletek megjelenítése" ++ ++#: appIcons.js:1398 ++msgid "New Window" ++msgstr "Új ablak" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Kilépés" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "Ablakok" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "Energiabeállítások" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "Eseménynaplók" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "Rendszer" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "Eszközkezelés" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "Lemezkezelés" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "Terminál" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "Rendszerfigyelő" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "Fájlok" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "Feladatsáv feloldása" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "Feladatsáv zárolása" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "„Dashből panel” beállításai" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "Ablakok visszaállítása" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "Asztal megjelenítése" ++ ++#: update.js:58 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "%s (%s) verzió érhető el" ++ ++#: update.js:59 ++msgid "Details" ++msgstr "Részletek" ++ ++#: update.js:60 ++msgid "Update" ++msgstr "Frissítés" ++ ++#: update.js:63 ++msgid "Already up to date" ++msgstr "Már naprakész" ++ ++#: update.js:148 ++msgid "Update successful, please log out/in" ++msgstr "Sikeres frissítés, jelentkezzen ki és be" ++ ++#: update.js:149 ++msgid "Log out" ++msgstr "Kijelentkezés" ++ ++#: update.js:153 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Sikeres frissítés, indítsa újra a GNOME Shell környezetet" ++ ++#: update.js:154 ++msgid "Restart GNOME Shell" ++msgstr "GNOME Shell újraindítása" ++ ++#: update.js:154 ++msgid "Restarting GNOME Shell..." ++msgstr "GNOME Shell újraindítása…" ++ ++#: update.js:160 ++msgid "Error: " ++msgstr "Hiba: " ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Még semmi!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Ha minimalizálásra van állítva, akkor a dupla kattintás az alkalmazás összes " ++"ablakát minimalizálja." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Shift + kattintás művelet" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Ablakok előtérbe hozása" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Ablak minimalizálása" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Új példány indítása" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Ablakok körbeléptetése" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Ablakok körbeléptetése + minimalizálás" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Önálló átkapcsolása / több előnézete" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "A középső kattintás viselkedése." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Középső kattintás művelet" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "A Shift + középső kattintás viselkedése." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Shift + középső kattintás művelet" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Kijelzők elszigetelése" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Kedvenc alkalmazások megjelenítése az összes kijelzőn" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Az óra megjelenítése az összes kijelzőn" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Az állapot menü megjelenítése az összes kijelzőn" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Alkalmazásmenü elemeinek integrálása" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Részletek megjelenítése menüpont" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Kijelölt alkalmazás kiemelése" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Ikon uralkodó színe" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Egyéni szín" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Kiemelés átlátszatlansága" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "Jelző magassága (képpont)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Jelző színe – ikon uralkodó szín" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Jelző színe – téma felülbírálása" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 nyitott ablak (vagy nem csoportosított)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Alkalmazás az összesre" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 nyitott ablak" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 nyitott ablak" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4+ nyitott ablak" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Eltérő használata a nem kijelölthöz" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Az alkalmazáscímek betűkészletmérete képpontban (alapértelmezetten 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Az alkalmazáscímek betűvastagsága" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "öröklés a témától" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normál" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "vékonyabb" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "félkövér" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "vastagabb" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Az alkalmazáscímek betűkészletszíne" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "" ++"Az alkalmazáscímek legnagyobb szélessége képpontban (alapértelmezetten 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Rögzített szélesség használata az alkalmazáscímeknél" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Az összes alkalmazáscím ugyanolyan széles lesz még akkor is, ha a szövegük " ++"rövidebb a legnagyobb szélességnél. A legnagyobb szélesség érték lesz " ++"használva rögzített szélességként." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Futásjelzők megjelenítése nem kijelölt alkalmazásoknál" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "A kedvenc ikonok használata alkalmazásindítókként" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Csak akkor rejtse el a panelt, amikor akadályozzák az ablakok " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "A panel el van rejtve ettől" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Az összes ablak" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Kijelölt ablakok" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Maximalizált ablakok" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Nyomás szükséges a képernyő szélénél a panel előhozásához" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Szükséges nyomási küszöbszint (képpont)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Szükséges nyomási időkorlát (ezredmásodperc)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Lehetővé teszi a panelnek, hogy előjöjjön teljes képernyős módban" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Csak a másodlagos panel elrejtése (többmonitoros beállítást igényel)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "például i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Gyorsbillentyű a panel előhozásához és megtartásához" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Szintaxis: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Elrejtési és előhozási animáció időkorlátja (ezredmásodperc)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Késleltetés a panel elrejtése előtt (ezredmásodperc)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "" ++"Az intelligens elrejtés indításkori engedélyezése előtti késleltetés " ++"(ezredmásodperc)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Megjelenítés előtti idő (ezredmásodperc, alapérték: 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Animáció ideje (ezredmásodperc)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Elrejtés előtti idő (ezredmásodperc, alapértelmezetten 100)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Azonnal az alkalmazásikonra kattintáskor" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Középső kattintás az előnézeten az ablak bezárásához" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Ablakelőnézetek előnyben részesített mérete (képpont)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Ablakelőnézetek Y képaránya (magasság)" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Ablakelőnézetek kitöltése (képpont)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Rögzített" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Ablakelőnézetek X képaránya (szélesség)" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Egyéni átlátszatlanság használata az előnézetek hátteréhez" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Ha le van tiltva, akkor az előnézetek háttere ugyanazzal az " ++"átlátszatlansággal rendelkezik mint a panel" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Bezáró gomb és fejléc helyzete" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Lent" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Fent" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Ablakelőnézet fejléceinek megjelenítése" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Az előnézet címeinek betűmérete (képpont)" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Az előnézet címeinek betűvastagsága" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Az előnézet címeinek betűszíne" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Ablakbetekintés engedélyezése" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Amikor rámutat egy ablakelőnézetre egy ideig, az ablak megkülönböztethetővé " ++"válik." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Ablakbetekintési módba lépés időkorlátja (ezredmásodperc)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Egy ablakelőnézet rámutatása közbeni tétlenség ideje, amely az " ++"ablakbetekintési módba lépéshez szükséges." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Ablakbetekintési módba átlátszatlansága" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"A betekintett ablak kivételével az összes ablaknál a saját átlátszatlanság " ++"ugyanarra az értékre van állítva." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Egérgörgetés-események közti késleltetés (ezredmásodperc)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Használja ezt az értéket a rögzített egérgörgetés-események számának " ++"korlátozásához." ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Szuper" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Szuper + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Gyorsbillentyű-előtag" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "" ++"A gyorsbillentyűk vagy Szuper + szám, vagy Szuper + Alt + szám lehetnek" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Soha" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Megjelenítés átmenetileg" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Mindig látható" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Szám rátét" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Az alkalmazás számainak átmeneti megjelenítése az ikonok fölött a " ++"gyorsbillentyűk használatakor." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Elrejtési időkorlát (ezredmásodperc)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "például q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Gyorsbillentyű a rátét megjelenítéséhez 2 másodpercre" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Ablakelőnézetek megjelenítése gyorsbillentyűvel" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Előnézetek megjelenítése, amikor az alkalmazásnak több példánya van" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Számsor" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Számbillentyűzet" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Mindkettő" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Gyorsbillentyűk bekapcsolva ezzel" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Annak kiválasztása, hogy a billentyűzet mely számbillentyűi legyenek " ++"használva a gyorsbillentyűk bekapcsolásához" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Jelenlegi „Alkalmazások megjelenítése” ikon" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Egy „Alkalmazások megjelenítése” képikon kiválasztása" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Egyéni „Alkalmazások megjelenítése” képikon" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "„Alkalmazások megjelenítése” ikon oldalsó kitöltése (képpont)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Az asztal előhozása, ha az „Asztal megjelenítése” gombra mutat" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Késleltetés az asztal előhozása előtt (ezredmásodperc)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Áttűnés időtartama (ezredmásodperc)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "A panel háttér-átlátszatlanságát a következő befolyásolja" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "" ++"Átlátszatlanság megváltoztatása, amikor egy ablak közelebb kerül mint " ++"(képpont)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Átlátszatlanság megváltoztatása erre (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Átlátszatlanságváltozás animációjának időtartama (ezredmásodperc)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Panel képernyő-pozíciója" ++ ++#: Settings.ui.h:145 ++msgid "Left" ++msgstr "Bal" ++ ++#: Settings.ui.h:146 ++msgid "Right" ++msgstr "Jobb" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Tálca helyzete" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Óra helye" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "A főpanel megjelenítése ezen" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Panelek megjelenítése az összes kijelzőn" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Panel intelligens elrejtése" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "A panel elrejtése vagy előhozása a beállítások szerint" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Pozíció" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Panelméret\n" ++"(alapérték: 48)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Alkalmazásikon margó\n" ++"(alapérték: 8)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Alkalmazásikon térköz\n" ++"(alapérték: 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Futásjelző pozíciója" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Futásjelző stílusa (kijelölt alkalmazás)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Pontok" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Négyzetek" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Szaggatott vonalak" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Darabolt" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Tömör" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Futásjelző stílusa (nem kijelölt alkalmazások)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "A paneltéma háttérszínének felülbírálása" ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "A paneltéma háttér-átlátszatlanságának felülbírálása" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Panel háttér-átlátszatlansága (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Dinamikus háttér-átlátszatlanság" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "" ++"Átlátszatlanság megváltoztatása, amikor egy ablak közel kerül a panelhez" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "A paneltéma színátmenetének felülbírálása" ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Színátmenet felső színe és átlátszatlansága (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Színátmenet alsó színe és átlátszatlansága (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Stílus" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Kedvenc alkalmazások megjelenítése" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Futó alkalmazások megjelenítése" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Alkalmazások ikon megjelenítése" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Alkalmazások megjelenítése animálása." ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Tevékenységek gomb megjelenítése" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Asztal gomb megjelenítése" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Alkalmazásmenü gomb megjelenítése" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"A felső sáv > Alkalmazásmenü megjelenítésének engedélyezve kell mennie a " ++"finomhangoló eszközben" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Ablakelőnézetek megjelenítése rámutatáskor" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Buboréksúgó megjelenítése rámutatáskor" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Munkaterületek elkülönítése" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Alkalmazások csoportosításának felbontása" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Viselkedés" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Viselkedés egy futó alkalmazás ikonjára való kattintáskor." ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Kattintás művelet" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Ablakok átkapcsolása" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Panel görgetése művelet" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Viselkedés, ha az egeret görgetik a panel fölött." ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Ikon görgetése művelet" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Viselkedés, ha az egeret görgetik egy alkalmazásikon fölött." ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Ne csináljon semmit" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Munkaterület váltása" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Ablakok léptetése" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Szuper + (0-9) engedélyezése gyorsbillentyűként az alkalmazások " ++"aktiválásához. Használható a Shift és a Ctrl billentyűkkel együtt is." ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "Gyorsbillentyűk használata az alkalmazások aktiválásához" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "Művelet" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tálca betűmérete\n" ++"(0 = téma alapértéke)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Bal doboz betűmérete\n" ++"(0 = téma alapértéke)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Tálcaelem kitöltése\n" ++"(-1 = téma alapértéke)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Állapotikon kitöltése\n" ++"(-1 = téma alapértéke)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Bal doboz kitöltése\n" ++"(-1 = téma alapértéke)" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "Alkalmazásváltások animálása" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "Új ablakok indításának animálása" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Eredeti gnome-shell dash megtartása (áttekintő)" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "Panelmenü gombjainak (például dátum menü) aktiválása csak kattintáskor" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "Alkalmazásikon másodlagos (jobb kattintásos) menüje" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "Finomhangolás" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "verzió: " ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Használja a lenti gombokat egy beállítási fájl létrehozásához a jelenlegi " ++"beállításokból, amely importálható egy másik gépen." ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "Beállítások exportálása és importálása" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "Exportálás fájlba" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "Importálás fájlból" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Ez lehetővé teszi a kiterjesztés frissítést közvetlenül a GitHub tárolóból." ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "Frissítések" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "Frissítések rendszeres ellenőrzése" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "Ellenőrzés most" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Ne feledje, hogy ezeket a hivatalos " ++"„Dash to Panel” kiterjesztéseket esetleg még nem vizsgálták felül az " ++"extensions.gnome.org oldalon! Tudjon meg többet" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Ehhez a programhoz SEMMILYEN GARANCIA NEM JÁR.\n" ++"Nézze meg a GNU General Public License 2. vagy későbbi verzióját a részletekért." ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "Névjegy" +diff --git a/po/it.po b/po/it.po +index 2d215b14..28634699 100644 +--- a/po/it.po ++++ b/po/it.po +@@ -554,3 +554,1402 @@ msgstr "Mostra il cestino" + #: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 + msgid "Show the trash icon in the desktop." + msgstr "Mostra il cestino sulla scrivania." ++ ++#: prefs.js:206 ++msgid "Show Desktop button height (px)" ++msgstr "Altezza tasto Mostra Desktop (px)" ++ ++#: prefs.js:206 ++msgid "Show Desktop button width (px)" ++msgstr "Larghezza tasto Mostra Desktop (px)" ++ ++#: prefs.js:218 ++msgid "Unavailable when gnome-shell top panel is present" ++msgstr "Non disponibile quando è presente il pannello superiore di gnome-shell" ++ ++#: prefs.js:293 ++msgid "Show Applications button" ++msgstr "Pulsante Mostra Applicazioni" ++ ++#: prefs.js:294 ++msgid "Activities button" ++msgstr "Pulsante Attività" ++ ++#: prefs.js:295 ++msgid "Taskbar" ++msgstr "Taskbar" ++ ++#: prefs.js:296 ++msgid "Date menu" ++msgstr "Data e ora" ++ ++#: prefs.js:297 ++msgid "System menu" ++msgstr "Menu di sistema" ++ ++#: prefs.js:298 ++msgid "Left box" ++msgstr "Contenitore di sinistra" ++ ++#: prefs.js:299 ++msgid "Center box" ++msgstr "Contenitore centrale" ++ ++#: prefs.js:300 ++msgid "Right box" ++msgstr "Contenitore di destra" ++ ++#: prefs.js:301 ++msgid "Desktop button" ++msgstr "Pulsante Desktop" ++ ++#: prefs.js:307 ++msgid "Move up" ++msgstr "Muovi verso l'alto" ++ ++#: prefs.js:309 ++msgid "Move down" ++msgstr "Muovi verso il basso" ++ ++#: prefs.js:311 ++msgid "Visible" ++msgstr "Visibile" ++ ++#: prefs.js:312 ++msgid "Select element position" ++msgstr "Seleziona posizione dell'elemento" ++ ++#: prefs.js:323 ++msgid "Stacked to top" ++msgstr "Allinea in alto" ++ ++#: prefs.js:323 ++msgid "Stacked to left" ++msgstr "Allinea a sinistra" ++ ++#: prefs.js:324 ++msgid "Stacked to bottom" ++msgstr "Allinea in basso" ++ ++#: prefs.js:324 ++msgid "Stacked to right" ++msgstr "Allinea a destra" ++ ++#: prefs.js:325 ++msgid "Centered" ++msgstr "Allinea al centro dello spazio disponibile" ++ ++#: prefs.js:326 ++msgid "Monitor Center" ++msgstr "Allinea al centro dello schermo" ++ ++#: prefs.js:345 ++msgid "More options" ++msgstr "Altre opzioni" ++ ++#: prefs.js:369 ++msgid "Show Applications options" ++msgstr "Opzioni Mostra Applicazioni" ++ ++#: prefs.js:376 prefs.js:433 prefs.js:576 prefs.js:894 prefs.js:1019 ++#: prefs.js:1146 prefs.js:1405 prefs.js:1500 prefs.js:1565 prefs.js:1608 ++#: prefs.js:1705 prefs.js:1739 prefs.js:1781 ++msgid "Reset to defaults" ++msgstr "Ripristina predefiniti" ++ ++#: prefs.js:426 ++msgid "Show Desktop options" ++msgstr "Opzioni Mostra Desktop" ++ ++#: prefs.js:569 ++msgid "Running Indicator Options" ++msgstr "Posizione indicatori di esecuzione" ++ ++#: prefs.js:732 ++msgid "Primary monitor" ++msgstr "Schermo principale" ++ ++#: prefs.js:732 ++msgid "Monitor " ++msgstr "Monitor " ++ ++#: prefs.js:887 ++msgid "Dynamic opacity options" ++msgstr "Opzioni opacità dinamica" ++ ++#: prefs.js:1012 ++msgid "Intellihide options" ++msgstr "Opzioni pannello Intellihide" ++ ++#: prefs.js:1139 ++msgid "Window preview options" ++msgstr "Opzioni anteprima finestre" ++ ++#: prefs.js:1398 ++msgid "Ungrouped application options" ++msgstr "Opzioni app non raggruppate" ++ ++#: prefs.js:1493 ++msgid "Customize middle-click behavior" ++msgstr "Personalizza azioni clic centrale" ++ ++#: prefs.js:1558 ++msgid "Customize panel scroll behavior" ++msgstr "Personalizza il comportamento di scorrimento sul pannello" ++ ++#: prefs.js:1601 ++msgid "Customize icon scroll behavior" ++msgstr "Personalizza il comportamento di scorrimento sull'icona" ++ ++#: prefs.js:1698 ++msgid "Advanced hotkeys options" ++msgstr "Opzioni avanzate scorciatoie" ++ ++#: prefs.js:1732 ++msgid "Secondary Menu Options" ++msgstr "Opzioni menu secondario" ++ ++#: prefs.js:1774 Settings.ui.h:226 ++msgid "Advanced Options" ++msgstr "Impostazioni avanzate" ++ ++#: prefs.js:1877 ++msgid "Export settings" ++msgstr "Esporta impostazioni" ++ ++#: prefs.js:1894 ++msgid "Import settings" ++msgstr "Importa impostazioni" ++ ++#: appIcons.js:1431 ++msgid "Show Details" ++msgstr "Mostra dettagli" ++ ++#: appIcons.js:1449 ++msgid "New Window" ++msgstr "Nuova finestra" ++ ++#: appIcons.js:1449 appIcons.js:1509 appIcons.js:1511 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Esci" ++ ++#: appIcons.js:1511 ++msgid "Windows" ++msgstr "Finestre" ++ ++#: appIcons.js:1860 ++msgid "Unlock taskbar" ++msgstr "Sblocca taskbar" ++ ++#: appIcons.js:1860 ++msgid "Lock taskbar" ++msgstr "Blocca taskbar" ++ ++#: appIcons.js:1865 ++msgid "Dash to Panel Settings" ++msgstr "Impostazioni Dash to Panel" ++ ++#: appIcons.js:1878 ++msgid "Restore Windows" ++msgstr "Ripristina finestre" ++ ++#: appIcons.js:1878 ++msgid "Show Desktop" ++msgstr "Mostra Desktop" ++ ++#: update.js:48 ++msgid "Unavailable when installed from extensions.gnome.org" ++msgstr "Non disponibile quando installato da extensions.gnome.org" ++ ++#: update.js:62 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "Disponibile la versione %s (%s)" ++ ++#: update.js:63 ++msgid "Details" ++msgstr "Dettagli" ++ ++#: update.js:64 ++msgid "Update" ++msgstr "Aggiorna" ++ ++#: update.js:67 ++msgid "Already up to date" ++msgstr "Già aggiornato" ++ ++#: update.js:75 ++msgid "Error: " ++msgstr "Errore: " ++ ++#: update.js:168 ++msgid "Update successful, please log out/in" ++msgstr "Aggiornamento eseguito correttamente, disconnettiti accedi nuovamente" ++ ++#: update.js:169 ++msgid "Log out" ++msgstr "Disconnettiti" ++ ++#: update.js:173 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Aggiornamento riuscito, riavvia GNOME Shell" ++ ++#: update.js:174 ++msgid "Restart GNOME Shell" ++msgstr "Riavvia GNOME Shell" ++ ++#: update.js:174 ++msgid "Restarting GNOME Shell..." ++msgstr "Riavvio della shell GNOME ..." ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Ancora niente!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Quando impostato su minimizza, il doppio clic minimizza tutte le finestre " ++"dell'app." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Azione Shift+Clic" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Solleva e visualizza finestra" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Minimizza finestra" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Apri una nuova istanza" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Cicla le finestre" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Cicla finestre + minimizza" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Commuta finestra singola e mostra anteprime" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Comportamento per clic-centrale." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Azione clic-centrale" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Comportamento per Shift+Clic-centrale." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Azione Shift+Clic-centrale" ++ ++#: Settings.ui.h:15 ++msgid "Integrate AppMenu items" ++msgstr "Integra elementi AppMenu" ++ ++#: Settings.ui.h:16 ++msgid "Show Details menu item" ++msgstr "Visualizza Mostra Dettagli" ++ ++#: Settings.ui.h:17 ++msgid "Highlight focused application" ++msgstr "Evidenzia applicazione con focus" ++ ++#: Settings.ui.h:18 ++msgid "Icon dominant color" ++msgstr "Colore dominante dell'icona" ++ ++#: Settings.ui.h:19 ++msgid "Custom color" ++msgstr "Colore personalizzato" ++ ++#: Settings.ui.h:20 ++msgid "Highlight opacity" ++msgstr "Opacità evidenziazione" ++ ++#: Settings.ui.h:21 ++msgid "Indicator size (px)" ++msgstr "Dimensione indicatore (px)" ++ ++#: Settings.ui.h:22 ++msgid "Indicator color - Icon Dominant" ++msgstr "Colore indicatore - Colore dominante dell'icona" ++ ++#: Settings.ui.h:23 ++msgid "Indicator color - Override Theme" ++msgstr "Colore indicatore - Ignora il tema" ++ ++#: Settings.ui.h:24 ++msgid "1 window open (or ungrouped)" ++msgstr "1 finestra aperta (o non raggruppata)" ++ ++#: Settings.ui.h:25 ++msgid "Apply to all" ++msgstr "Applica a tutte" ++ ++#: Settings.ui.h:26 ++msgid "2 windows open" ++msgstr "2 finestre aperte" ++ ++#: Settings.ui.h:27 ++msgid "3 windows open" ++msgstr "3 finestre aperte" ++ ++#: Settings.ui.h:28 ++msgid "4+ windows open" ++msgstr "4+ finestre aperte" ++ ++#: Settings.ui.h:29 ++msgid "Use different for unfocused" ++msgstr "Personalizza per app senza focus" ++ ++#: Settings.ui.h:30 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Dimensione font (px) dei titoli delle app (predef. 14)" ++ ++#: Settings.ui.h:31 ++msgid "Font weight of application titles" ++msgstr "Stile font dei titoli delle applicazioni" ++ ++#: Settings.ui.h:32 ++msgid "inherit from theme" ++msgstr "eredita dal tema" ++ ++#: Settings.ui.h:33 ++msgid "normal" ++msgstr "normale" ++ ++#: Settings.ui.h:34 ++msgid "lighter" ++msgstr "leggero" ++ ++#: Settings.ui.h:35 ++msgid "bold" ++msgstr "grassetto" ++ ++#: Settings.ui.h:36 ++msgid "bolder" ++msgstr "grosso" ++ ++#: Settings.ui.h:37 ++msgid "Font color of the application titles" ++msgstr "Colore font dei titoli delle applicazioni" ++ ++#: Settings.ui.h:38 ++msgid "Font color of the minimized application titles" ++msgstr "Colore font titoli delle applicazioni minimizzate" ++ ++#: Settings.ui.h:39 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Larghezza massima (px) dei titoli delle app (predef. 160)" ++ ++#: Settings.ui.h:40 ++msgid "Use a fixed width for the application titles" ++msgstr "Usa larghezza fissa per i titoli delle app" ++ ++#: Settings.ui.h:41 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"I titoli delle applicazioni hanno la stessa larghezza anche se i testi sono " ++"più corti della larghezza massima. Viene usato il valore di larghezza " ++"massima." ++ ++#: Settings.ui.h:42 ++msgid "Display running indicators on unfocused applications" ++msgstr "Mostra indicatori di esecuzione nelle app senza focus" ++ ++#: Settings.ui.h:43 ++msgid "Use the favorite icons as application launchers" ++msgstr "Usa le icone dei Preferiti come lanciatori delle app" ++ ++#: Settings.ui.h:44 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Nascondi pannello solo quando è ostruito dalle finestre " ++ ++#: Settings.ui.h:45 ++msgid "The panel hides from" ++msgstr "Il pannello si nasconde con" ++ ++#: Settings.ui.h:46 ++msgid "All windows" ++msgstr "Tutte le finestre" ++ ++#: Settings.ui.h:47 ++msgid "Focused windows" ++msgstr "Finestre con focus" ++ ++#: Settings.ui.h:48 ++msgid "Maximized windows" ++msgstr "Finestre massimizzate" ++ ++#: Settings.ui.h:49 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Richiedi pressione a bordo schermo per mostrare il pannello" ++ ++#: Settings.ui.h:50 ++msgid "Required pressure threshold (px)" ++msgstr "Soglia di pressione richiesta (px)" ++ ++#: Settings.ui.h:51 ++msgid "Required pressure timeout (ms)" ++msgstr "Timeout pressione richiesta (ms)" ++ ++#: Settings.ui.h:52 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Permetti al pannello di apparire quando in modalità fullscreen" ++ ++#: Settings.ui.h:53 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Nascondi solo i pannelli secondari (richiede l'opzione multi-monitor)" ++ ++#: Settings.ui.h:54 ++msgid "e.g. i" ++msgstr "es. i" ++ ++#: Settings.ui.h:55 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Scorciatoie per mostrare e nascondere il pannello" ++ ++#: Settings.ui.h:56 ++msgid "Syntax: , , , " ++msgstr "Sintassi: , , , " ++ ++#: Settings.ui.h:57 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Durata animazione mostra/nascondi (ms)" ++ ++#: Settings.ui.h:58 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Ritardo prima di nascondere il pannello (ms)" ++ ++#: Settings.ui.h:59 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Ritardo iniziale (ms) prima di abilitare intellihide" ++ ++#: Settings.ui.h:60 ++msgid "Time (ms) before showing (400 is default)" ++msgstr "" ++"Tempo (ms) prima della visualizzazione (400 è l'impostazione predefinita)" ++ ++#: Settings.ui.h:61 ++msgid "Animation time (ms)" ++msgstr "Durata animazione (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Tempo (ms) prima di nascondersi (100 è l'impostazione predefinita)" ++ ++#: Settings.ui.h:63 ++msgid "Immediate on application icon click" ++msgstr "Immediatamente al clic sull'icona dell'applicazione" ++ ++#: Settings.ui.h:64 ++msgid "Middle click on the preview to close the window" ++msgstr "Clic centrale sull'anteprima per chiudere la finestra" ++ ++#: Settings.ui.h:65 ++msgid "Window previews preferred size (px)" ++msgstr "Dimensioni preferite delle anteprime delle finestre (px)" ++ ++#: Settings.ui.h:66 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Proporzioni anteprime delle finestre Y (altezza)" ++ ++#: Settings.ui.h:67 ++msgid "Window previews padding (px)" ++msgstr "Spaziatura anteprime finestre (px)" ++ ++#: Settings.ui.h:68 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:69 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:70 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:71 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:72 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:73 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:74 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:75 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:76 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:77 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:78 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:79 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:80 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:81 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:82 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:83 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:84 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:85 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:86 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:87 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:88 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:89 ++msgid "Fixed" ++msgstr "Fisso" ++ ++#: Settings.ui.h:90 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Proporzioni anteprime delle finestre X (larghezza)" ++ ++#: Settings.ui.h:91 ++msgid "Use custom opacity for the previews background" ++msgstr "Usa l'opacità personalizzata per lo sfondo delle anteprime" ++ ++#: Settings.ui.h:92 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Se disabilitato, lo sfondo delle anteprime ha la stessa opacità del pannello" ++ ++#: Settings.ui.h:93 ++msgid "Close button and header position" ++msgstr "Pulsante di chiusura e posizione dell'intestazione" ++ ++#: Settings.ui.h:94 ++msgid "Bottom" ++msgstr "Basso" ++ ++#: Settings.ui.h:95 ++msgid "Top" ++msgstr "Alto" ++ ++#: Settings.ui.h:96 ++msgid "Display window preview headers" ++msgstr "Visualizza le intestazioni di anteprima della finestra" ++ ++#: Settings.ui.h:97 ++msgid "Font size (px) of the preview titles" ++msgstr "Dimensione carattere (px) dei titoli di anteprima" ++ ++#: Settings.ui.h:98 ++msgid "Font weight of the preview titles" ++msgstr "Dimensione del carattere dei titoli dell'anteprima" ++ ++#: Settings.ui.h:99 ++msgid "Font color of the preview titles" ++msgstr "Colore del carattere dei titoli dell'anteprima" ++ ++#: Settings.ui.h:100 ++msgid "Enable window peeking" ++msgstr "Abilita separazione finestre" ++ ++#: Settings.ui.h:101 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "Restando sulla finestra per qualche istante, la finestra si separa." ++ ++#: Settings.ui.h:102 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Timeout ingresso modalità finestra separata (ms)" ++ ++#: Settings.ui.h:103 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:104 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Tempo di inattività sopra una finestra richiesto per entrare in modalità " ++"separata." ++ ++#: Settings.ui.h:105 ++msgid "Window peeking mode opacity" ++msgstr "Opacità modalità finestra separata" ++ ++#: Settings.ui.h:106 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:107 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"Tutte le finestre, tranne quella visualizzata, hanno la stessa opacità." ++ ++#: Settings.ui.h:108 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Ritardo tra gli eventi di scorrimento del mouse (ms)" ++ ++#: Settings.ui.h:109 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Utilizzare questo valore per limitare il numero di eventi di scorrimento del " ++"mouse acquisiti." ++ ++#: Settings.ui.h:110 ++msgid "Show popup when changing workspace" ++msgstr "Mostra popup cambiando spazio di lavoro" ++ ++#: Settings.ui.h:111 ++msgid "This affects workspace popup when scrolling on the panel only." ++msgstr "" ++"Questo influisce sul popup spazi di lavoro solo quando si scorre sul pannello" ++ ++#: Settings.ui.h:112 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:113 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:114 ++msgid "Hotkeys prefix" ++msgstr "Prefisso scorciatoie" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Le scorciatoie saranno Super+Numero o Super+Alt+Numero" ++ ++#: Settings.ui.h:116 ++msgid "Never" ++msgstr "Mai" ++ ++#: Settings.ui.h:117 ++msgid "Show temporarily" ++msgstr "Temporanea" ++ ++#: Settings.ui.h:118 ++msgid "Always visible" ++msgstr "Sempre visibile" ++ ++#: Settings.ui.h:119 ++msgid "Number overlay" ++msgstr "Sovrimpressione numero" ++ ++#: Settings.ui.h:120 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Mostra temporaneamente i numeri delle applicazioni sulle icone quando si " ++"usano le scorciatoie." ++ ++#: Settings.ui.h:121 ++msgid "Hide timeout (ms)" ++msgstr "Timeout visualizzazione (ms)" ++ ++#: Settings.ui.h:122 ++msgid "e.g. q" ++msgstr "es. q" ++ ++#: Settings.ui.h:123 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Scorciatoia per la sovrapposizione di 2 secondi" ++ ++#: Settings.ui.h:124 ++msgid "Show window previews on hotkey" ++msgstr "Mostra anteprime finestre da hotkey" ++ ++#: Settings.ui.h:125 ++msgid "Show previews when the application have multiple instances" ++msgstr "Mostra anteprime quando l'applicazione ha più istanze" ++ ++#: Settings.ui.h:126 ++msgid "Number row" ++msgstr "Numero riga" ++ ++#: Settings.ui.h:127 ++msgid "Numeric keypad" ++msgstr "Tastierino numerico" ++ ++#: Settings.ui.h:128 ++msgid "Both" ++msgstr "Entrambi" ++ ++#: Settings.ui.h:129 ++msgid "Hotkeys are activated with" ++msgstr "I tasti di scelta rapida sono attivati con" ++ ++#: Settings.ui.h:130 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Seleziona la tipologia dei tasti numerici utilizzati per attivare i tasti di " ++"scelta rapida" ++ ++#: Settings.ui.h:131 ++msgid "Current Show Applications icon" ++msgstr "Icona Mostra Applicazioni attuale" ++ ++#: Settings.ui.h:132 ++msgid "Select a Show Applications image icon" ++msgstr "Seleziona icona per Mostra Applicazioni" ++ ++#: Settings.ui.h:133 ++msgid "Custom Show Applications image icon" ++msgstr "Icona Mostra Applicazioni personalizzata" ++ ++#: Settings.ui.h:134 ++msgid "Show Applications icon side padding (px)" ++msgstr "Spaziatura a lato dell'icona Mostra Applicazioni (px)" ++ ++#: Settings.ui.h:135 ++msgid "Override escape key and return to desktop" ++msgstr "" ++"Sostituisci il tasto escape e ritorna al desktop anziché alla panoramica" ++ ++#: Settings.ui.h:136 ++msgid "Animate Show Applications." ++msgstr "Animazione Mostra Applicazioni." ++ ++#: Settings.ui.h:137 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "" ++"Rivela il desktop quando si passa il cursore sul pulsante Mostra desktop" ++ ++#: Settings.ui.h:138 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Ritardo prima di rivelare il desktop (ms)" ++ ++#: Settings.ui.h:139 ++msgid "Fade duration (ms)" ++msgstr "Durata dissolvenza (ms)" ++ ++#: Settings.ui.h:140 ++msgid "The panel background opacity is affected by" ++msgstr "L'opacità dello pannello è influenzato da" ++ ++#: Settings.ui.h:141 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Cambia l'opacità quando una finestra è più vicina di (px)" ++ ++#: Settings.ui.h:143 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Imposta opacità al (%)" ++ ++#: Settings.ui.h:144 ++msgid "Opacity change animation duration (ms)" ++msgstr "Durata animazione cambio opacità (ms)" ++ ++#: Settings.ui.h:145 ++msgid "Display the main panel on" ++msgstr "Mostra pannello principale su" ++ ++#: Settings.ui.h:146 ++msgid "Display panels on all monitors" ++msgstr "Mostra pannelli su tutti i monitor" ++ ++#: Settings.ui.h:147 ++msgid "Panel Intellihide" ++msgstr "Pannello Intellihide" ++ ++#: Settings.ui.h:148 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Mostra e nascondi il pannello secondo le preferenze" ++ ++#: Settings.ui.h:149 ++msgid "Order and positions on monitor" ++msgstr "Ordinamento e posizione sullo schermo" ++ ++#: Settings.ui.h:150 ++msgid "Apply changes to all monitors" ++msgstr "Applica a tutti gli schermi" ++ ++#: Settings.ui.h:151 ++msgid "Panel screen position" ++msgstr "Posizione pannello sullo schermo" ++ ++#: Settings.ui.h:152 ++msgid "Left" ++msgstr "Sinistra" ++ ++#: Settings.ui.h:153 ++msgid "Right" ++msgstr "Destra" ++ ++#: Settings.ui.h:154 ++msgid "Position" ++msgstr "Posizione" ++ ++#: Settings.ui.h:155 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Dimensione pannello\n" ++"(predefinito 48)" ++ ++#: Settings.ui.h:157 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Margine icone app\n" ++"(predefinito 8)" ++ ++#: Settings.ui.h:159 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Spaziatura icone app\n" ++"(predefinito 4)" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator position" ++msgstr "Posizione indicatore di esecuzione" ++ ++#: Settings.ui.h:162 ++msgid "Running indicator style (Focused app)" ++msgstr "Stile indicatore di esecuzione (app con focus)" ++ ++#: Settings.ui.h:163 ++msgid "Dots" ++msgstr "Puntini" ++ ++#: Settings.ui.h:164 ++msgid "Squares" ++msgstr "Quadrati" ++ ++#: Settings.ui.h:165 ++msgid "Dashes" ++msgstr "Trattini" ++ ++#: Settings.ui.h:166 ++msgid "Segmented" ++msgstr "Segmenti" ++ ++#: Settings.ui.h:167 ++msgid "Solid" ++msgstr "Solidi" ++ ++#: Settings.ui.h:168 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:169 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:170 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Stile indicatore di esecuzione (app senza focus)" ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background color " ++msgstr "Ignora il colore di sfondo del pannello " ++ ++#: Settings.ui.h:172 ++msgid "Override panel theme background opacity" ++msgstr "Ignora l'opacità del pannello" ++ ++#: Settings.ui.h:174 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Opacità di sfondo del pannello (%)" ++ ++#: Settings.ui.h:175 ++msgid "Dynamic background opacity" ++msgstr "Opacità di sfondo dinamica" ++ ++#: Settings.ui.h:176 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Cambia l'opacità quando una finestra è vicina al pannello" ++ ++#: Settings.ui.h:177 ++msgid "Override panel theme gradient " ++msgstr "Ignora gradiente del pannello " ++ ++#: Settings.ui.h:179 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Colore superiore del gradiente e opacità (%)" ++ ++#: Settings.ui.h:181 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Colore inferiore del gradiente e opacità (%)" ++ ++#: Settings.ui.h:182 ++msgid "Style" ++msgstr "Stile" ++ ++#: Settings.ui.h:183 ++msgid "Show favorite applications" ++msgstr "Mostra applicazioni preferite" ++ ++#: Settings.ui.h:184 ++msgid "Show running applications" ++msgstr "Mostra le applicazioni in esecuzione" ++ ++#: Settings.ui.h:185 ++msgid "Show favorite applications on secondary panels" ++msgstr "Mostra le applicazioni preferite sui pannelli secondari" ++ ++#: Settings.ui.h:186 ++msgid "Show AppMenu button" ++msgstr "Mostra pulsante AppMenu" ++ ++#: Settings.ui.h:187 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "In Estensioni deve essere abilitato il Menù dell'applicazione" ++ ++#: Settings.ui.h:188 ++msgid "Show window previews on hover" ++msgstr "Mostra anteprime finestre al passaggio" ++ ++#: Settings.ui.h:189 ++msgid "Show tooltip on hover" ++msgstr "Mostra suggerimento al passaggio" ++ ++#: Settings.ui.h:190 ++msgid "Isolate Workspaces" ++msgstr "Isola spazi di lavoro" ++ ++#: Settings.ui.h:191 ++msgid "Isolate monitors" ++msgstr "Isola monitor" ++ ++#: Settings.ui.h:192 ++msgid "Ungroup applications" ++msgstr "Non raggruppare applicazioni" ++ ++#: Settings.ui.h:193 ++msgid "Behavior" ++msgstr "Comportamento" ++ ++#: Settings.ui.h:194 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Comportamento al clic sull'icona di un'app in esecuzione." ++ ++#: Settings.ui.h:195 ++msgid "Click action" ++msgstr "Azione al clic" ++ ++#: Settings.ui.h:196 ++msgid "Toggle windows" ++msgstr "Commuta le finestre" ++ ++#: Settings.ui.h:197 ++msgid "Scroll panel action" ++msgstr "Azione scorrimento pannello" ++ ++#: Settings.ui.h:198 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Comportamento durante lo scorrimento del mouse sul pannello." ++ ++#: Settings.ui.h:199 ++msgid "Scroll icon action" ++msgstr "Azione scorrimento icona" ++ ++#: Settings.ui.h:200 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "" ++"Comportamento quando si scorre il mouse sopra l'icona di un'applicazione." ++ ++#: Settings.ui.h:201 ++msgid "Do nothing" ++msgstr "Nessuna azione" ++ ++#: Settings.ui.h:202 ++msgid "Switch workspace" ++msgstr "Cambia spazio di lavoro" ++ ++#: Settings.ui.h:203 ++msgid "Cycle windows" ++msgstr "Cicla le finestre" ++ ++#: Settings.ui.h:204 ++msgid "Change volume" ++msgstr "Cambia il volume" ++ ++#: Settings.ui.h:205 ++msgid "Same as panel" ++msgstr "Stesso del pannello" ++ ++#: Settings.ui.h:206 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Abilita Super+(0-9) come scorciatoia per attivare le app. Può essere usato " ++"assieme a Shift e Ctrl." ++ ++#: Settings.ui.h:207 ++msgid "Use hotkeys to activate apps" ++msgstr "Usa scorciatoie per attivare app" ++ ++#: Settings.ui.h:208 ++msgid "Action" ++msgstr "Azioni" ++ ++#: Settings.ui.h:209 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Dimens. Font Tray\n" ++"(0 = predefinito)" ++ ++#: Settings.ui.h:211 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Dimens. Font LeftBox\n" ++"(0 = predefinito)" ++ ++#: Settings.ui.h:213 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Spaziatura Icone Tray\n" ++"(-1 = predefinito)" ++ ++#: Settings.ui.h:215 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Spaziatura icone stato\n" ++"(-1 = predefinito)" ++ ++#: Settings.ui.h:217 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Spaziatura LeftBox\n" ++"(-1 = predefinito)" ++ ++#: Settings.ui.h:219 ++msgid "Animate switching applications" ++msgstr "Animazione passaggio tra applicazioni" ++ ++#: Settings.ui.h:220 ++msgid "Animate launching new windows" ++msgstr "Animazione apertura nuove finestre" ++ ++#: Settings.ui.h:221 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Mantieni dash originale di gnome-shell (schermata panoramica)" ++ ++#: Settings.ui.h:222 ++msgid "Force Activities hot corner on primary monitor" ++msgstr "Forza angolo attivo delle attività sul monitor principale" ++ ++#: Settings.ui.h:223 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "" ++"Attiva i pulsanti del menu del pannello (ad es. Menu della data) solo al clic" ++ ++#: Settings.ui.h:224 ++msgid "Keep original gnome-shell top panel" ++msgstr "Mantieni il pannello superiore della gnome-shell originale" ++ ++#: Settings.ui.h:225 ++msgid "App icon secondary (right-click) menu" ++msgstr "Menu secondario (clic destro) delle icone" ++ ++#: Settings.ui.h:227 ++msgid "Fine-Tune" ++msgstr "Perfeziona" ++ ++#: Settings.ui.h:228 ++msgid "version: " ++msgstr "versione: " ++ ++#: Settings.ui.h:229 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:230 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Usa i tasti qui sotto per salvare in un file le tue preferenze attuali che " ++"potranno essere importate su altri computer." ++ ++#: Settings.ui.h:231 ++msgid "Export and import settings" ++msgstr "Esporta e importa impostazioni" ++ ++#: Settings.ui.h:232 ++msgid "Export to file" ++msgstr "Esporta su file" ++ ++#: Settings.ui.h:233 ++msgid "Import from file" ++msgstr "Importa da file" ++ ++#: Settings.ui.h:234 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Ciò consente di aggiornare l'estensione direttamente dal repository GitHub." ++ ++#: Settings.ui.h:235 ++msgid "Updates" ++msgstr "Aggiornamenti" ++ ++#: Settings.ui.h:236 ++msgid "Periodically check for updates" ++msgstr "Controlla periodicamente per gli aggiornamenti" ++ ++#: Settings.ui.h:237 ++msgid "Check now" ++msgstr "Controlla ora" ++ ++#: Settings.ui.h:238 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Attenzione, queste versioni " ++"ufficiali di Dash to Panel potrebbero non essere ancora esaminate su " ++"extensions.gnome.org! Leggi di più" ++ ++#: Settings.ui.h:239 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Questo programma è fornito SENZA NESSUNA GARANZIA.\n" ++"Vedere GNU General Public License, versione 2 o successive per dettagli." ++ ++#: Settings.ui.h:241 ++msgid "About" ++msgstr "Informazioni su" ++ ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "In alto, con le icone dei plugin raggruppate in bassoa" ++ ++msgid "Left, with plugin icons collapsed to right" ++msgstr "A sinistra, con le icone dei plugin raggruppate a destra" ++ ++msgid "Top, with fixed center plugin icons" ++msgstr "In alto, con le icone dei plugin fisse al centro" ++ ++msgid "Left, with fixed center plugin icons" ++msgstr "A sinistra, con le icone dei plugin fisse al centro" ++ ++msgid "Top, with floating center plugin icons" ++msgstr "In cima, con le icone dei plugin flottanti al centro" ++ ++msgid "Left, with floating center plugin icons" ++msgstr "Sinistra, con le icone dei plugin flottanti al centro" ++ ++msgid "Center, fixed in middle of monitor" ++msgstr "Centrato, fisso al centro del monitor" ++ ++msgid "Center, floating between top and bottom elements" ++msgstr "Centrato, flottante tra elementi in cima e in basso" ++ ++msgid "Center, floating between left and right elements" ++msgstr "Centrato, flottante tra elementi a destra e sinistra" ++ ++msgid "Top of plugin icons" ++msgstr "In cima alle icone dei plugin" ++ ++msgid "Left of plugin icons" ++msgstr "Sinistra delle icone plugin" ++ ++msgid "Bottom of plugin icons" ++msgstr "In fondo alle icone dei plugin" ++ ++msgid "Right of plugin icons" ++msgstr "Destra delle icone plugin" ++ ++msgid "Top of system indicators" ++msgstr "In cima agli indicatori di sistema" ++ ++msgid "Left of system indicators" ++msgstr "Sinistra degli indicatori di sistema" ++ ++msgid "Bottom of system indicators" ++msgstr "In fondo agli indicatori di sistema" ++ ++msgid "Right of system indicators" ++msgstr "Destra degli indicatori di sistema" ++ ++msgid "Left of taskbar" ++msgstr "Sinistra della taskbar" ++ ++msgid "Bottom of taskbar" ++msgstr "In fondo alla taskbar" ++ ++msgid "Right of taskbar" ++msgstr "Destra della taskbar" ++ ++msgid "Display the clock on additional panels" ++msgstr "Mostra l'orologio su pannelli aggiuntivi" ++ ++msgid "Display the clock on secondary panels" ++msgstr "Visualizza l'orologio su pannelli secondari" ++ ++msgid "Display the status menu on additional panels" ++msgstr "Mostra il menu di stato su pannelli aggiuntivi" ++ ++msgid "Display the status menu on secondary panels" ++msgstr "Mostra il menu di stato su pannelli secondari" ++ ++msgid "Taskbar position" ++msgstr "Posizione taskbar" ++ ++msgid "Clock location" ++msgstr "Posizione orologio" ++ ++msgid "" ++"For the following 2 options, \"additional\" refers to panels that are " ++"displayed in addition to the gnome-shell top panel." ++msgstr "" ++"Per le seguenti 2 opzioni, \"aggiuntivo\" si riferisce ai pannelli che " ++"vengono visualizzati in aggiunta al pannello superiore di gnome-shell." ++ ++msgid "Show Applications icon" ++msgstr "Mostra icona Applicazioni" ++ ++msgid "Multi-monitors options" ++msgstr "Opzioni multi-monitor" ++ ++msgid "Event logs" ++msgstr "Registro degli eventi" ++ ++msgid "System" ++msgstr "Sistema" ++ ++msgid "Device Management" ++msgstr "Gestione dispositivi" ++ ++msgid "Disk Management" ++msgstr "Gestione disco" ++ ++msgid "Terminal" ++msgstr "Terminale" ++ ++msgid "Extensions" ++msgstr "Estensioni" ++ ++msgid "Files" ++msgstr "Esplora file" ++ ++msgid "Display favorite applications on all monitors" ++msgstr "Mostra applicazioni preferite su tutti i monitor" ++ ++msgid "Highlight color" ++msgstr "Colore evidenziazione" ++ ++msgid "Preview timeout on icon leave (ms)" ++msgstr "Timeout anteprima uscendo dall'icona (ms)" ++ ++msgid "" ++"If set too low, the window preview of running applications may seem to close " ++"too quickly when trying to enter the popup. If set too high, the preview may " ++"linger too long when moving to an adjacent icon." ++msgstr "" ++"Se troppo basso, l'anteprima delle applicazioni in esecuzione potrebbe " ++"chiudersi troppo presto quando si entra nel popup. Se troppo alto, " ++"l'anteprima potrebbe persistere troppo a lungo quando si cambia icona." ++ ++msgid "Middle click to close window" ++msgstr "Clic centrale per chiudere la finestra" ++ ++msgid "Width of the window previews (px)" ++msgstr "Larghezza delle anteprime (px)" ++ ++msgid "Height of the window previews (px)" ++msgstr "Altezza delle anteprime (px)" ++ ++msgid "Padding of the window previews (px)" ++msgstr "Spaziatura delle anteprime (px)" ++ ++msgid "Natural" ++msgstr "Naturale" ++ ++msgid "Left side of panel" ++msgstr "A sinistra del pannello" ++ ++msgid "Centered in content" ++msgstr "Centrato nel contenuto" ++ ++msgid "Github" ++msgstr "GitHub" +diff --git a/po/ja.po b/po/ja.po +index df5646d2..1bcaf344 100644 +--- a/po/ja.po ++++ b/po/ja.po +@@ -394,7 +394,7 @@ msgstr "端末を開く" + msgid "Change Background…" + msgstr "背景の変更…" + +-#: desktopGrid.js:335 ++#: desktopGrid.js:335 appIcons.js:1846 + msgid "Settings" + msgstr "設定" + +@@ -474,6 +474,1321 @@ msgstr "ゴミ箱アイコンを表示する" + msgid "Show the trash icon in the desktop." + msgstr "デスクトップにゴミ箱のアイコンを表示します。" + ++#: Settings.ui:4898 Settings.ui:5259 ++#, fuzzy ++msgid "Left" ++msgstr "" ++"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"左回り\n" ++"#-#-#-#-# ja.po #-#-#-#-#\n" ++"左" ++ ++#: Settings.ui:4918 Settings.ui:5276 ++#, fuzzy ++msgid "Right" ++msgstr "" ++"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"右回り\n" ++"#-#-#-#-# ja.po #-#-#-#-#\n" ++"右" ++ ++#: appIcons.js:1440 ++#, fuzzy ++msgid "New Window" ++msgstr "" ++"#-#-#-#-# ja.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"新しいウィンドウで開く\n" ++"#-#-#-#-# ja.po #-#-#-#-#\n" ++"新しいウィンドウ" ++ ++#: Settings.ui:43 ++msgid "Nothing yet!" ++msgstr "まだ何もありません!" ++ ++#: Settings.ui:98 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"最小化に設定する場合、ダブルクリックでそのアプリケーションのすべてのウィンド" ++"ウを最小化します。" ++ ++#: Settings.ui:116 ++msgid "Shift+Click action" ++msgstr "Shift + クリックの動作" ++ ++#: Settings.ui:130 Settings.ui:201 Settings.ui:272 Settings.ui:6529 ++msgid "Raise windows" ++msgstr "ウィンドウを最前面に移動" ++ ++#: Settings.ui:131 Settings.ui:202 Settings.ui:273 ++msgid "Minimize window" ++msgstr "ウィンドウを最小化" ++ ++#: Settings.ui:132 Settings.ui:203 Settings.ui:274 Settings.ui:6530 ++msgid "Launch new instance" ++msgstr "新規インスタンスを起動" ++ ++#: Settings.ui:133 Settings.ui:204 Settings.ui:275 Settings.ui:6526 ++msgid "Cycle through windows" ++msgstr "ウィンドウを循環表示" ++ ++#: Settings.ui:134 Settings.ui:205 Settings.ui:276 Settings.ui:6525 ++msgid "Cycle windows + minimize" ++msgstr "ウィンドウを循環 + 最小化" ++ ++#: Settings.ui:135 Settings.ui:206 Settings.ui:277 Settings.ui:6527 ++msgid "Toggle single / Preview multiple" ++msgstr "ウィンドウが 1 つなら切り替え" ++ ++#: Settings.ui:169 ++msgid "Behavior for Middle-Click." ++msgstr "中クリック時の挙動です。" ++ ++#: Settings.ui:187 ++msgid "Middle-Click action" ++msgstr "中クリックの動作" ++ ++#: Settings.ui:240 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Shift + 中クリック時の挙動です。" ++ ++#: Settings.ui:258 ++msgid "Shift+Middle-Click action" ++msgstr "Shift + 中クリックの動作" ++ ++#: Settings.ui:337 ++msgid "Integrate AppMenu items" ++msgstr "アプリケーションメニューの項目を統合" ++ ++#: Settings.ui:383 ++msgid "Show Details menu item" ++msgstr "詳細を表示するメニュー項目を表示" ++ ++#: Settings.ui:481 ++msgid "Highlight focused application" ++msgstr "フォーカスされたアプリをハイライト" ++ ++#: Settings.ui:512 ++msgid "Icon dominant color" ++msgstr "アイコンのドミナントカラー" ++ ++#: Settings.ui:537 ++msgid "Custom color" ++msgstr "カスタムカラー" ++ ++#: Settings.ui:562 ++msgid "Highlight opacity" ++msgstr "ハイライトの不透明度" ++ ++#: Settings.ui:614 ++msgid "Indicator size (px)" ++msgstr "インジケーターのサイズ (px)" ++ ++#: Settings.ui:658 ++msgid "Indicator color - Icon Dominant" ++msgstr "インジケーターの色 - アイコンのドミナント" ++ ++#: Settings.ui:704 ++msgid "Indicator color - Override Theme" ++msgstr "インジケーターの色 - テーマを上書き" ++ ++#: Settings.ui:747 Settings.ui:933 ++msgid "1 window open (or ungrouped)" ++msgstr "ウィンドウを 1 つ開く (または非グループ化)" ++ ++#: Settings.ui:762 Settings.ui:948 ++msgid "Apply to all" ++msgstr "すべてに適用" ++ ++#: Settings.ui:798 Settings.ui:984 ++msgid "2 windows open" ++msgstr "ウィンドウを 2 つ開く" ++ ++#: Settings.ui:811 Settings.ui:1009 ++msgid "3 windows open" ++msgstr "ウィンドウを 3 つ開く" ++ ++#: Settings.ui:824 Settings.ui:1034 ++msgid "4+ windows open" ++msgstr "ウィンドウを 4 つ以上開く" ++ ++#: Settings.ui:890 ++msgid "Use different for unfocused" ++msgstr "非フォーカスの場合は異なる色を使用" ++ ++#: Settings.ui:1141 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "アプリケーションタイトルのフォントサイズ (px) (初期値は 14)" ++ ++#: Settings.ui:1172 ++msgid "Font weight of application titles" ++msgstr "アプリケーションタイトルのフォントの幅" ++ ++#: Settings.ui:1186 Settings.ui:2911 ++msgid "inherit from theme" ++msgstr "テーマに依存" ++ ++#: Settings.ui:1187 Settings.ui:2912 ++msgid "normal" ++msgstr "普通" ++ ++#: Settings.ui:1188 Settings.ui:2913 ++msgid "lighter" ++msgstr "細い" ++ ++#: Settings.ui:1189 Settings.ui:2914 ++msgid "bold" ++msgstr "太い" ++ ++#: Settings.ui:1190 Settings.ui:2915 ++msgid "bolder" ++msgstr "より太い" ++ ++#: Settings.ui:1220 ++msgid "Font color of the application titles" ++msgstr "アプリケーションタイトルのフォントの色" ++ ++#: Settings.ui:1263 ++msgid "Font color of the minimized application titles" ++msgstr "アプリケーションタイトルのフォントの色 (最小化時)" ++ ++#: Settings.ui:1306 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "アプリケーションタイトルの最大幅 (px) (初期値は 160)" ++ ++#: Settings.ui:1351 ++msgid "Use a fixed width for the application titles" ++msgstr "アプリケーションタイトルの幅を固定" ++ ++#: Settings.ui:1376 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"アプリケーションタイトルが最大幅より短い場合でも、幅を維持します。最大幅の値" ++"が固定幅の値として使用されます。" ++ ++#: Settings.ui:1412 ++msgid "Display running indicators on unfocused applications" ++msgstr "フォーカスされていないアプリケーションのインジケーターを表示" ++ ++#: Settings.ui:1454 ++msgid "Use the favorite icons as application launchers" ++msgstr "アプリケーションランチャーとしてお気に入りアイコンを使用" ++ ++#: Settings.ui:1552 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "ウィンドウが重なっている場合にのみパネルを隠す " ++ ++#: Settings.ui:1584 ++msgid "The panel hides from" ++msgstr "対象のウィンドウ" ++ ++#: Settings.ui:1598 Settings.ui:4355 ++msgid "All windows" ++msgstr "すべてのウィンドウ" ++ ++#: Settings.ui:1599 Settings.ui:4356 ++msgid "Focused windows" ++msgstr "フォーカスされたウィンドウ" ++ ++#: Settings.ui:1600 Settings.ui:4357 ++msgid "Maximized windows" ++msgstr "最大化されたウィンドウ" ++ ++#: Settings.ui:1638 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "マウスカーソルを画面端へ押し当てることでパネルを表示" ++ ++#: Settings.ui:1670 ++msgid "Required pressure threshold (px)" ++msgstr "表示に必要な値 (px)" ++ ++#: Settings.ui:1699 ++msgid "Required pressure timeout (ms)" ++msgstr "押し当てのタイムアウト (ミリ秒)" ++ ++#: Settings.ui:1754 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "フルスクリーンモード時でのパネルの表示を許可" ++ ++#: Settings.ui:1798 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "マルチモニター環境でセカンダリーパネルのみ隠す" ++ ++#: Settings.ui:1841 ++msgid "e.g. i" ++msgstr "例: i" ++ ++#: Settings.ui:1854 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "パネルを表示して固定するキーボードショートカット" ++ ++#: Settings.ui:1866 Settings.ui:3641 ++msgid "Syntax: , , , " ++msgstr "シンタックス: " ++ ++#: Settings.ui:1901 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "表示/非表示アニメーションの長さ (ミリ秒)" ++ ++#: Settings.ui:1947 ++msgid "Delay before hiding the panel (ms)" ++msgstr "パネルを隠す前の遅延 (ミリ秒)" ++ ++#: Settings.ui:1994 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "起動時に Intellihide を有効にする前の遅延 (ミリ秒)" ++ ++#: Settings.ui:2158 ++msgid "Time (ms) before showing (400 is default)" ++msgstr "表示までの時間 (ミリ秒) (初期値は 400)" ++ ++#: Settings.ui:2172 ++msgid "Animation time (ms)" ++msgstr "アニメーション時間 (ミリ秒)" ++ ++#: Settings.ui:2205 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "隠すまでの時間 (ミリ秒) (初期値は 100)" ++ ++#: Settings.ui:2229 ++msgid "Immediate on application icon click" ++msgstr "アプリケーションアイコンをクリックしたら即隠す" ++ ++#: Settings.ui:2285 ++msgid "Middle click on the preview to close the window" ++msgstr "プレビュー上での中クリックでウィンドウを閉じる" ++ ++#: Settings.ui:2329 ++msgid "Window previews preferred size (px)" ++msgstr "ウィンドウプレビューの優先サイズ (px)" ++ ++#: Settings.ui:2360 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "ウィンドウプレビューの Y アスペクト比 (高さ)" ++ ++#: Settings.ui:2375 ++msgid "Window previews padding (px)" ++msgstr "ウィンドウプレビューのパディング (px)" ++ ++#: Settings.ui:2415 Settings.ui:2493 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui:2416 Settings.ui:2494 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui:2417 Settings.ui:2495 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui:2418 Settings.ui:2496 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui:2419 Settings.ui:2497 Settings.ui:2616 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui:2420 Settings.ui:2498 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui:2421 Settings.ui:2499 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui:2422 Settings.ui:2500 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui:2423 Settings.ui:2501 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui:2424 Settings.ui:2502 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui:2425 Settings.ui:2503 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui:2426 Settings.ui:2504 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui:2427 Settings.ui:2505 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui:2428 Settings.ui:2506 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui:2429 Settings.ui:2507 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui:2430 Settings.ui:2508 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui:2431 Settings.ui:2509 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui:2432 Settings.ui:2510 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui:2433 Settings.ui:2511 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui:2434 Settings.ui:2512 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui:2435 Settings.ui:2513 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui:2446 Settings.ui:2524 ++msgid "Fixed" ++msgstr "固定" ++ ++#: Settings.ui:2469 ++msgid "Window previews aspect ratio X (width)" ++msgstr "ウィンドウプレビューの X アスペクト比 (幅)" ++ ++#: Settings.ui:2564 ++msgid "Use custom opacity for the previews background" ++msgstr "プレビューの背景にカスタム不透明度を使用" ++ ++#: Settings.ui:2578 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "無効の場合、プレビューの背景はパネルの不透明度と同一になります" ++ ++#: Settings.ui:2654 ++msgid "Close button and header position" ++msgstr "閉じるボタンとヘッダーの位置" ++ ++#: Settings.ui:2671 Settings.ui:4859 Settings.ui:5224 ++msgid "Bottom" ++msgstr "下" ++ ++#: Settings.ui:2689 Settings.ui:4878 Settings.ui:5241 ++msgid "Top" ++msgstr "上" ++ ++#: Settings.ui:2735 ++msgid "Display window preview headers" ++msgstr "ウィンドウプレビューのヘッダーを表示" ++ ++#: Settings.ui:2807 ++msgid "Icon size (px) of the window preview" ++msgstr "ウィンドウプレビューのアイコンサイズ (px)" ++ ++#: Settings.ui:2821 ++msgid "If disabled, the previews icon size will be based on headerbar size" ++msgstr "無効の場合、ヘッダーバーのサイズを基準にしてアイコンサイズを設定します" ++ ++#: Settings.ui:2869 ++msgid "Font size (px) of the preview titles" ++msgstr "プレビュータイトルのフォントサイズ (px)" ++ ++#: Settings.ui:2896 ++msgid "Font weight of the preview titles" ++msgstr "プレビュータイトルのフォント幅" ++ ++#: Settings.ui:2941 ++msgid "Font color of the preview titles" ++msgstr "プレビュータイトルのフォントの色" ++ ++#: Settings.ui:2992 ++msgid "Enable window peeking" ++msgstr "ウィンドウの覗き見を有効化" ++ ++#: Settings.ui:3018 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"ウィンドウのプレビューにしばらくの間マウスホバーし続けると、そのウィンドウ以" ++"外が透明化されます。" ++ ++#: Settings.ui:3043 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "ウィンドウ覗き見モードに入る時間 (ミリ秒)" ++ ++#: Settings.ui:3057 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui:3072 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"ウィンドウ覗き見モードに入るには、ウィンドウのプレビューにマウスホバーしたま" ++"ま、しばらく動かさずに待つ必要があります。" ++ ++#: Settings.ui:3104 ++msgid "Window peeking mode opacity" ++msgstr "ウィンドウ覗き見モードの不透明度" ++ ++#: Settings.ui:3118 Settings.ui:3903 Settings.ui:4448 Settings.ui:5607 ++#: Settings.ui:5825 Settings.ui:5863 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui:3132 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"選択したウィンドウ以外のすべてのウィンドウの不透明度が、設定した値になりま" ++"す。" ++ ++#: Settings.ui:3212 Settings.ui:3300 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "マウススクロールイベント間の遅延 (ミリ秒)" ++ ++#: Settings.ui:3226 Settings.ui:3314 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "マウススクロールを検知した後、指定した時間スクロールに反応しません。" ++ ++#: Settings.ui:3348 ++msgid "Show popup when changing workspace" ++msgstr "ワークスペース切り替え時にポップアップを表示" ++ ++#: Settings.ui:3362 ++msgid "This affects workspace popup when scrolling on the panel only." ++msgstr "" ++"これはパネル上でスクロールしたときのワークスペースのポップアップにのみ影響し" ++"ます。" ++ ++#: Settings.ui:3444 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui:3445 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui:3459 ++msgid "Hotkeys prefix" ++msgstr "ホットキーのプレフィックス" ++ ++#: Settings.ui:3471 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "ホットキーは Super + 数字キー、Super + Alt + 数字キーのどちらかです。" ++ ++#: Settings.ui:3509 ++msgid "Never" ++msgstr "表示しない" ++ ++#: Settings.ui:3510 ++msgid "Show temporarily" ++msgstr "一時的に表示" ++ ++#: Settings.ui:3511 ++msgid "Always visible" ++msgstr "常に表示" ++ ++#: Settings.ui:3525 ++msgid "Number overlay" ++msgstr "番号の表示" ++ ++#: Settings.ui:3537 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"ホットキー使用時、アプリケーションのアイコン上に番号を一時的に表示します。" ++ ++#: Settings.ui:3586 ++msgid "Hide timeout (ms)" ++msgstr "非表示にするまでの時間 (ミリ秒)" ++ ++#: Settings.ui:3616 ++msgid "e.g. q" ++msgstr "例: q" ++ ++#: Settings.ui:3629 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "番号を 2 秒間表示するショートカットキー" ++ ++#: Settings.ui:3676 ++msgid "Show window previews on hotkey" ++msgstr "ホットキーでウィンドウプレビューを表示" ++ ++#: Settings.ui:3703 ++msgid "Show previews when the application have multiple instances" ++msgstr "アプリケーションのインスタンスが複数ある場合はプレビューを表示します" ++ ++#: Settings.ui:3740 ++msgid "Number row" ++msgstr "数字キー" ++ ++#: Settings.ui:3741 ++msgid "Numeric keypad" ++msgstr "テンキー" ++ ++#: Settings.ui:3742 ++msgid "Both" ++msgstr "両方" ++ ++#: Settings.ui:3756 ++msgid "Hotkeys are activated with" ++msgstr "ホットキーに使用するキー" ++ ++#: Settings.ui:3768 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "キーボードのどちら側の数字キーをホットキーに使用するかを選択します" ++ ++#: Settings.ui:3823 ++msgid "Current Show Applications icon" ++msgstr "現在のアプリケーション表示アイコン" ++ ++#: Settings.ui:3853 ++msgid "Select a Show Applications image icon" ++msgstr "アプリケーション表示の画像アイコンを選択" ++ ++#: Settings.ui:3865 ++msgid "Custom Show Applications image icon" ++msgstr "カスタムアイコン" ++ ++#: Settings.ui:3916 ++msgid "Show Applications icon side padding (px)" ++msgstr "アプリケーション表示アイコンのパディング (px)" ++ ++#: Settings.ui:3963 ++msgid "Override escape key and return to desktop" ++msgstr "Esc キーで直接デスクトップに戻る" ++ ++#: Settings.ui:3999 ++msgid "Animate Show Applications." ++msgstr "アプリケーションの表示にアニメーションを使用" ++ ++#: Settings.ui:4102 ++msgid "Override Show Desktop line color" ++msgstr "デスクトップ表示ボタンの境目の色を上書き" ++ ++#: Settings.ui:4173 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "デスクトップ表示ボタンにマウスホバーでデスクトップを表示" ++ ++#: Settings.ui:4204 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "表示するまでの遅延時間 (ミリ秒)" ++ ++#: Settings.ui:4234 ++msgid "Fade duration (ms)" ++msgstr "フェード時間 (ミリ秒)" ++ ++#: Settings.ui:4341 ++msgid "The panel background opacity is affected by" ++msgstr "パネル背景の不透明度に影響を与えるウィンドウ" ++ ++#: Settings.ui:4403 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "不透明度を変更するウィンドウの距離 (px)" ++ ++#: Settings.ui:4433 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "不透明度を次に変更 (%)" ++ ++#: Settings.ui:4496 ++msgid "Opacity change animation duration (ms)" ++msgstr "不透明度変更アニメーションの継続時間 (ミリ秒)" ++ ++#: Settings.ui:4572 ++msgid "Display the main panel on" ++msgstr "メインパネルの表示" ++ ++#: Settings.ui:4614 ++msgid "Display panels on all monitors" ++msgstr "すべてのモニターにパネルを表示" ++ ++#: Settings.ui:4681 ++msgid "Panel Intellihide" ++msgstr "パネルの Intellihide" ++ ++#: Settings.ui:4745 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "パネルを自動的に隠したり表示したりします" ++ ++#: Settings.ui:4798 ++msgid "Order and positions on monitor" ++msgstr "モニター上での順序と位置" ++ ++#: Settings.ui:4819 ++msgid "Apply changes to all monitors" ++msgstr "変更内容をすべてのモニターに適用する" ++ ++#: Settings.ui:4843 ++msgid "Panel screen position" ++msgstr "パネルの表示位置" ++ ++#: Settings.ui:4991 ++msgid "Position" ++msgstr "位置" ++ ++#: Settings.ui:5036 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"パネルのサイズ\n" ++"(初期値は 48)" ++ ++#: Settings.ui:5086 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"アプリのアイコンのマージン\n" ++"(初期値は 8)" ++ ++#: Settings.ui:5135 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"アプリのアイコンのパディング\n" ++"(初期値は 4)" ++ ++#: Settings.ui:5208 ++msgid "Running indicator position" ++msgstr "実行中インジケーターの位置" ++ ++#: Settings.ui:5321 ++msgid "Running indicator style (Focused app)" ++msgstr "実行中インジケーターのスタイル (フォーカス)" ++ ++#: Settings.ui:5365 Settings.ui:5426 ++msgid "Dots" ++msgstr "" ++ ++#: Settings.ui:5366 Settings.ui:5427 ++msgid "Squares" ++msgstr "" ++ ++#: Settings.ui:5367 Settings.ui:5428 ++msgid "Dashes" ++msgstr "" ++ ++#: Settings.ui:5368 Settings.ui:5429 ++msgid "Segmented" ++msgstr "" ++ ++#: Settings.ui:5369 Settings.ui:5430 ++msgid "Solid" ++msgstr "" ++ ++#: Settings.ui:5370 Settings.ui:5431 ++msgid "Ciliora" ++msgstr "" ++ ++#: Settings.ui:5371 Settings.ui:5432 ++msgid "Metro" ++msgstr "" ++ ++#: Settings.ui:5410 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "実行中インジケーターのスタイル (非フォーカス)" ++ ++#: Settings.ui:5486 ++msgid "Override panel theme background color " ++msgstr "パネルテーマの背景色を上書き " ++ ++#: Settings.ui:5559 ++msgid "Override panel theme background opacity" ++msgstr "パネルテーマ背景の不透明度を上書き" ++ ++#: Settings.ui:5592 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "パネル背景の不透明度 (%)" ++ ++#: Settings.ui:5626 ++msgid "Dynamic background opacity" ++msgstr "動的な背景透過" ++ ++#: Settings.ui:5641 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "パネルにウィンドウが近づいたら不透明度を変更します" ++ ++#: Settings.ui:5748 ++msgid "Override panel theme gradient " ++msgstr "パネルテーマのグラデーションを上書き " ++ ++#: Settings.ui:5781 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "グラデーションの開始色と不透明度 (%)" ++ ++#: Settings.ui:5794 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "グラデーションの終了色と不透明度 (%)" ++ ++#: Settings.ui:5910 ++msgid "Style" ++msgstr "スタイル" ++ ++#: Settings.ui:5969 ++msgid "Show favorite applications" ++msgstr "お気に入りのアプリケーションを表示" ++ ++#: Settings.ui:5982 ++msgid "Show running applications" ++msgstr "実行中のアプリケーションを表示" ++ ++#: Settings.ui:6019 ++msgid "Show favorite applications on secondary panels" ++msgstr "お気に入りのアプリケーションをセカンダリーパネルに表示" ++ ++#: Settings.ui:6064 ++msgid "Show AppMenu button" ++msgstr "アプリケーションメニューボタンを表示" ++ ++#: Settings.ui:6078 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Tweak Tool で「トップバー」 > 「アプリケーションメニュー」を有効にする必要が" ++"あります" ++ ++#: Settings.ui:6164 ++msgid "Show window previews on hover" ++msgstr "マウスホバー時にウィンドウのプレビューを表示" ++ ++#: Settings.ui:6190 ++msgid "Show tooltip on hover" ++msgstr "マウスホバー時にツールチップを表示" ++ ++#: Settings.ui:6235 ++msgid "Isolate Workspaces" ++msgstr "アイコンをワークスペースごとに表示" ++ ++#: Settings.ui:6261 ++msgid "Isolate monitors" ++msgstr "モニターを分離" ++ ++#: Settings.ui:6306 ++msgid "Click empty space to close overview" ++msgstr "オーバービュー画面で何もないところをクリックしたらデスクトップに戻る" ++ ++#: Settings.ui:6338 ++msgid "Ungroup applications" ++msgstr "アプリケーションを非グループ化" ++ ++#: Settings.ui:6421 ++msgid "Behavior" ++msgstr "挙動" ++ ++#: Settings.ui:6466 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "起動しているアプリケーションのアイコンをクリックしたときの挙動です。" ++ ++#: Settings.ui:6483 ++msgid "Click action" ++msgstr "クリック時の動作" ++ ++#: Settings.ui:6528 ++msgid "Toggle windows" ++msgstr "ウィンドウを切り替え" ++ ++#: Settings.ui:6587 ++msgid "Scroll panel action" ++msgstr "パネルスクロールの動作" ++ ++#: Settings.ui:6601 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "パネル上でマウススクロールしたときの挙動です。" ++ ++#: Settings.ui:6630 ++msgid "Scroll icon action" ++msgstr "アイコンスクロールの動作" ++ ++#: Settings.ui:6644 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "アプリアイコン上でマウススクロールしたときの挙動です。" ++ ++#: Settings.ui:6693 Settings.ui:6711 ++msgid "Do nothing" ++msgstr "何もしない" ++ ++#: Settings.ui:6694 ++msgid "Switch workspace" ++msgstr "ワークスペースを切り替え" ++ ++#: Settings.ui:6695 Settings.ui:6712 ++msgid "Cycle windows" ++msgstr "ウィンドウを循環表示" ++ ++#: Settings.ui:6696 ++msgid "Change volume" ++msgstr "音量を変更" ++ ++#: Settings.ui:6713 ++msgid "Same as panel" ++msgstr "パネルと同様" ++ ++#: Settings.ui:6785 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"アプリを起動するショートカット (Super + 0〜9) を有効にします。Shift や Ctrl " ++"と共に使用できます。" ++ ++#: Settings.ui:6803 ++msgid "Use hotkeys to activate apps" ++msgstr "ホットキーを使用してアプリを起動" ++ ++#: Settings.ui:6886 ++msgid "Action" ++msgstr "動作" ++ ++#: Settings.ui:6933 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"トレイのフォントサイズ\n" ++"(0 = テーマの既定値)" ++ ++#: Settings.ui:6964 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"LeftBox のフォントサイズ\n" ++"(0 = テーマの既定値)" ++ ++#: Settings.ui:7037 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"トレイアイテムのパディング\n" ++"(-1 = テーマの既定値)" ++ ++#: Settings.ui:7068 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"ステータスアイコンのパディング\n" ++"(-1 = テーマの既定値)" ++ ++#: Settings.ui:7099 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"LeftBox のパディング\n" ++"(-1 = テーマの既定値)" ++ ++#: Settings.ui:7170 ++msgid "Animate switching applications" ++msgstr "アプリケーション切り替え時のアニメーション効果" ++ ++#: Settings.ui:7207 ++msgid "Animate launching new windows" ++msgstr "新しいウィンドウを開くときのアニメーション効果" ++ ++#: Settings.ui:7258 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "オリジナルの GNOME Shell Dash を維持 (オーバービュー画面)" ++ ++#: Settings.ui:7283 ++msgid "Force Activities hot corner on primary monitor" ++msgstr "プライマリーモニターのアクティビティホットコーナーを強制" ++ ++#: Settings.ui:7308 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "パネルの日付メニューやシステムメニューをクリック時のみ有効化" ++ ++#: Settings.ui:7333 ++msgid "Keep original gnome-shell top panel" ++msgstr "オリジナルの GNOME Shell トップバーを維持" ++ ++#: Settings.ui:7400 ++msgid "App icon secondary (right-click) menu" ++msgstr "アプリアイコンのセカンダリー (右クリック) メニュー" ++ ++#: Settings.ui:7470 ++msgid "Fine-Tune" ++msgstr "微調整" ++ ++#: Settings.ui:7516 ++msgid "version: " ++msgstr "バージョン: " ++ ++#: Settings.ui:7546 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui:7599 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"以下のボタンを使用して現在の設定から設定ファイルを作成し、別のマシンにイン" ++"ポートできます。" ++ ++#: Settings.ui:7617 ++msgid "Export and import settings" ++msgstr "設定のエクスポートとインポート" ++ ++#: Settings.ui:7627 ++msgid "Export to file" ++msgstr "ファイルにエクスポート" ++ ++#: Settings.ui:7639 ++msgid "Import from file" ++msgstr "ファイルからインポート" ++ ++#: Settings.ui:7695 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "GitHub のリポジトリから拡張機能を直接アップデートできます。" ++ ++#: Settings.ui:7714 ++msgid "Updates" ++msgstr "アップデート" ++ ++#: Settings.ui:7727 ++msgid "Periodically check for updates" ++msgstr "アップデートを定期的に確認" ++ ++#: Settings.ui:7755 ++msgid "Check now" ++msgstr "今すぐ確認" ++ ++#: Settings.ui:7779 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"この機能でアップデートされる Dash to " ++"Panel は公式のものではありますが、まだ extensions.gnome.org でレビューされて" ++"いない可能性があることにご注意ください! 詳細はこちら" ++ ++#: Settings.ui:7811 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"このプログラムは全くの無保証です。\n" ++"詳しくは GNU General Public License, version 2 またはそれ以降 " ++"をご確認ください。" ++ ++#: Settings.ui:7832 ++msgid "About" ++msgstr "Dash to Panel について" ++ ++#: appIcons.js:1422 ++msgid "Show Details" ++msgstr "詳細を表示" ++ ++#: Settings.ui:136 Settings.ui:207 Settings.ui:278 appIcons.js:1440 ++#: appIcons.js:1500 appIcons.js:1502 ++msgid "Quit" ++msgstr "終了" ++ ++#: appIcons.js:1502 ++msgid "Windows" ++msgstr "個のウィンドウ" ++ ++#: appIcons.js:1792 ++msgid "Power options" ++msgstr "電源オプション" ++ ++#: appIcons.js:1797 ++msgid "Event logs" ++msgstr "イベントログ" ++ ++#: appIcons.js:1802 ++msgid "System" ++msgstr "システム" ++ ++#: appIcons.js:1807 ++msgid "Device Management" ++msgstr "デバイス管理" ++ ++#: appIcons.js:1812 ++msgid "Disk Management" ++msgstr "ディスク管理" ++ ++#: appIcons.js:1826 ++msgid "Terminal" ++msgstr "端末" ++ ++#: appIcons.js:1831 ++msgid "System monitor" ++msgstr "システムモニター" ++ ++#: appIcons.js:1836 ++msgid "Files" ++msgstr "ファイル" ++ ++#: appIcons.js:1841 ++msgid "Extensions" ++msgstr "拡張機能" ++ ++#: appIcons.js:1851 ++msgid "Unlock taskbar" ++msgstr "タスクバーをロック解除" ++ ++#: appIcons.js:1851 ++msgid "Lock taskbar" ++msgstr "タスクバーをロック" ++ ++#: appIcons.js:1856 ++msgid "Dash to Panel Settings" ++msgstr "Dash to Panel の設定" ++ ++#: appIcons.js:1869 ++msgid "Restore Windows" ++msgstr "ウィンドウを復元" ++ ++#: appIcons.js:1869 ++msgid "Show Desktop" ++msgstr "デスクトップを表示" ++ ++#: panel.js:201 ++msgid "Top Bar" ++msgstr "トップバー" ++ ++#: prefs.js:206 ++msgid "Show Desktop button height (px)" ++msgstr "デスクトップ表示ボタンの高さ (px)" ++ ++#: prefs.js:206 ++msgid "Show Desktop button width (px)" ++msgstr "デスクトップ表示ボタンの幅 (px)" ++ ++#: prefs.js:218 ++msgid "Unavailable when gnome-shell top panel is present" ++msgstr "GNOME Shell のトップバーが表示されている場合は利用できません" ++ ++#: prefs.js:293 ++msgid "Show Applications button" ++msgstr "アプリケーション表示ボタン" ++ ++#: prefs.js:294 ++msgid "Activities button" ++msgstr "アクティビティボタン" ++ ++#: prefs.js:295 ++msgid "Taskbar" ++msgstr "タスクバー" ++ ++#: prefs.js:296 ++msgid "Date menu" ++msgstr "日付メニュー" ++ ++#: prefs.js:297 ++msgid "System menu" ++msgstr "システムメニュー" ++ ++#: prefs.js:298 ++msgid "Left box" ++msgstr "左ボックス" ++ ++#: prefs.js:299 ++msgid "Center box" ++msgstr "中央ボックス" ++ ++#: prefs.js:300 ++msgid "Right box" ++msgstr "右ボックス" ++ ++#: prefs.js:301 ++msgid "Desktop button" ++msgstr "デスクトップボタン" ++ ++#: prefs.js:307 ++msgid "Move up" ++msgstr "上へ移動" ++ ++#: prefs.js:309 ++msgid "Move down" ++msgstr "下へ移動" ++ ++#: prefs.js:311 ++msgid "Visible" ++msgstr "表示" ++ ++#: prefs.js:312 ++msgid "Select element position" ++msgstr "要素の位置を選択してください" ++ ++#: prefs.js:323 ++msgid "Stacked to top" ++msgstr "上寄せ" ++ ++#: prefs.js:323 ++msgid "Stacked to left" ++msgstr "左寄せ" ++ ++#: prefs.js:324 ++msgid "Stacked to bottom" ++msgstr "下寄せ" ++ ++#: prefs.js:324 ++msgid "Stacked to right" ++msgstr "右寄せ" ++ ++#: prefs.js:325 ++msgid "Centered" ++msgstr "中央" ++ ++#: prefs.js:326 ++msgid "Monitor Center" ++msgstr "モニターの中央" ++ ++#: prefs.js:345 ++msgid "More options" ++msgstr "その他のオプション" ++ ++#: prefs.js:369 ++msgid "Show Applications options" ++msgstr "アプリケーション表示のオプション" ++ ++#: prefs.js:376 prefs.js:433 prefs.js:576 prefs.js:894 prefs.js:1037 ++#: prefs.js:1164 prefs.js:1450 prefs.js:1545 prefs.js:1610 prefs.js:1653 ++#: prefs.js:1750 prefs.js:1784 prefs.js:1826 ++msgid "Reset to defaults" ++msgstr "初期設定に戻す" ++ ++#: prefs.js:426 ++msgid "Show Desktop options" ++msgstr "デスクトップ表示のオプション" ++ ++#: prefs.js:569 ++msgid "Running Indicator Options" ++msgstr "実行中インジケーターのオプション" ++ ++#: prefs.js:732 ++msgid "Primary monitor" ++msgstr "プライマリーモニター" ++ ++#: prefs.js:732 ++msgid "Monitor " ++msgstr "モニター " ++ ++#: prefs.js:887 ++msgid "Dynamic opacity options" ++msgstr "動的不透明度のオプション" ++ ++#: prefs.js:1030 ++msgid "Intellihide options" ++msgstr "Intellihide のオプション" ++ ++#: prefs.js:1157 ++msgid "Window preview options" ++msgstr "ウィンドウプレビューのオプション" ++ ++#: prefs.js:1443 ++msgid "Ungrouped application options" ++msgstr "アプリケーション非グループ化のオプション" ++ ++#: prefs.js:1538 ++msgid "Customize middle-click behavior" ++msgstr "中クリックの挙動のカスタマイズ" ++ ++#: prefs.js:1603 ++msgid "Customize panel scroll behavior" ++msgstr "パネルスクロールの挙動のカスタマイズ" ++ ++#: prefs.js:1646 ++msgid "Customize icon scroll behavior" ++msgstr "アイコンスクロールの挙動のカスタマイズ" ++ ++#: prefs.js:1743 ++msgid "Advanced hotkeys options" ++msgstr "高度なホットキーのオプション" ++ ++#: prefs.js:1777 ++msgid "Secondary Menu Options" ++msgstr "右クリックメニューのオプション" ++ ++#: Settings.ui:7448 prefs.js:1819 ++msgid "Advanced Options" ++msgstr "高度なオプション" ++ ++#: prefs.js:1922 ++msgid "Export settings" ++msgstr "設定のエクスポート" ++ ++#: prefs.js:1939 ++msgid "Import settings" ++msgstr "設定のインポート" ++ ++#: update.js:48 ++msgid "Unavailable when installed from extensions.gnome.org" ++msgstr "extensions.gnome.org からインストールした場合は利用できません" ++ ++#: update.js:62 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "バージョン %s (%s) が利用可能です" ++ ++#: update.js:63 ++msgid "Details" ++msgstr "詳細" ++ ++#: update.js:64 ++msgid "Update" ++msgstr "アップデート" ++ ++#: update.js:67 ++msgid "Already up to date" ++msgstr "すでに最新です" ++ ++#: update.js:75 ++msgid "Error: " ++msgstr "エラー: " ++ ++#: update.js:168 ++msgid "Update successful, please log out/in" ++msgstr "アップデート成功: ログインしなおしてください" ++ ++#: update.js:169 ++msgid "Log out" ++msgstr "ログアウト" ++ ++#: update.js:173 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "アップデート成功: GNOME Shell を再起動してください" ++ ++#: update.js:174 ++msgid "Restart GNOME Shell" ++msgstr "GNOME Shell を再起動" ++ ++#: update.js:174 ++msgid "Restarting GNOME Shell..." ++msgstr "GNOME Shell を再起動しています..." ++ ++#: windowPreview.js:934 ++msgid "Move to current Workspace" ++msgstr "現在のワークスペースに移動" ++ + #~ msgid "Attach modal dialog to the parent window" + #~ msgstr "モーダルダイアログを親ウィンドウに結び付ける" + +@@ -557,12 +1872,6 @@ msgstr "デスクトップにゴミ箱のアイコンを表示します。" + #~ msgid "Normal" + #~ msgstr "標準" + +-#~ msgid "Left" +-#~ msgstr "左回り" +- +-#~ msgid "Right" +-#~ msgstr "右回り" +- + #~ msgid "Upside-down" + #~ msgstr "逆さま" + +@@ -608,9 +1917,6 @@ msgstr "デスクトップにゴミ箱のアイコンを表示します。" + #~ msgid "Drag here to add favorites" + #~ msgstr "ドラッグでお気に入りに追加" + +-#~ msgid "New Window" +-#~ msgstr "新しいウィンドウで開く" +- + #~ msgid "Remove from Favorites" + #~ msgstr "お気に入りから削除" + +@@ -661,3 +1967,125 @@ msgstr "デスクトップにゴミ箱のアイコンを表示します。" + + #~ msgid "Configure display settings..." + #~ msgstr "ディスプレイの設定..." ++ ++#~ msgid "Display favorite applications on all monitors" ++#~ msgstr "すべてのモニターにお気に入りのアプリケーションを表示" ++ ++#~ msgid "Display the clock on all monitors" ++#~ msgstr "すべてのモニターに時計を表示" ++ ++#~ msgid "Display the status menu on all monitors" ++#~ msgstr "すべてのモニターにステータスメニューを表示" ++ ++#~ msgid "Taskbar position" ++#~ msgstr "タスクバーの位置" ++ ++#~ msgid "Clock location" ++#~ msgstr "時計の位置" ++ ++#~ msgid "Show Applications icon" ++#~ msgstr "アプリケーションアイコンを表示" ++ ++#~ msgid "Top, with plugin icons collapsed to bottom" ++#~ msgstr "上 (プラグインアイコンは下寄せ)" ++ ++#~ msgid "Left, with plugin icons collapsed to right" ++#~ msgstr "左 (プラグインアイコンは右寄せ)" ++ ++#~ msgid "Top, with fixed center plugin icons" ++#~ msgstr "上 (プラグインアイコンは中央に固定)" ++ ++#~ msgid "Left, with fixed center plugin icons" ++#~ msgstr "左 (プラグインアイコンは中央に固定)" ++ ++#~ msgid "Top, with floating center plugin icons" ++#~ msgstr "上 (プラグインアイコンは中央かつ非固定)" ++ ++#~ msgid "Left, with floating center plugin icons" ++#~ msgstr "左 (プラグインアイコンは中央かつ非固定)" ++ ++#~ msgid "Center, fixed in middle of monitor" ++#~ msgstr "中央 (モニターの中央に固定)" ++ ++#~ msgid "Center, floating between top and bottom elements" ++#~ msgstr "中央 (上側と下側のエレメント間に表示)" ++ ++#~ msgid "Center, floating between left and right elements" ++#~ msgstr "中央 (右側と左側のエレメント間に表示)" ++ ++#~ msgid "Top of plugin icons" ++#~ msgstr "プラグインアイコンの上" ++ ++#~ msgid "Left of plugin icons" ++#~ msgstr "プラグインアイコンの左" ++ ++#~ msgid "Bottom of plugin icons" ++#~ msgstr "プラグインアイコンの下" ++ ++#~ msgid "Right of plugin icons" ++#~ msgstr "プラグインアイコンの右" ++ ++#~ msgid "Top of system indicators" ++#~ msgstr "システムインジケーターの上" ++ ++#~ msgid "Left of system indicators" ++#~ msgstr "システムインジケーターの左" ++ ++#~ msgid "Bottom of system indicators" ++#~ msgstr "システムインジケーターの下" ++ ++#~ msgid "Right of system indicators" ++#~ msgstr "システムインジケーターの右" ++ ++#~ msgid "Left of taskbar" ++#~ msgstr "タスクバーの左" ++ ++#~ msgid "Bottom of taskbar" ++#~ msgstr "タスクバーの下" ++ ++#~ msgid "Right of taskbar" ++#~ msgstr "タスクバーの右" ++ ++#~ msgid "Multi-monitors options" ++#~ msgstr "マルチモニターのオプション" ++ ++#~ msgid "Panel position" ++#~ msgstr "パネルの位置" ++ ++#~ msgid "Panel is shown on the Bottom or Top of the screen." ++#~ msgstr "パネルは画面の下か上に表示されます。" ++ ++#~ msgid "48" ++#~ msgstr "48" ++ ++#~ msgid "Panel size" ++#~ msgstr "パネルのサイズ" ++ ++#~ msgid "Set the size of the panel." ++#~ msgstr "パネルのサイズをセットします。" ++ ++#~ msgid "Dot position" ++#~ msgstr "ドットの位置" ++ ++#~ msgid "Running indicators are shown on the Bottom or Top of the screen." ++#~ msgstr "実行中インジケーターは画面の下か上に表示されます。" ++ ++#~ msgid "Style of the running indicator (focused)" ++#~ msgstr "実行中インジケーターのスタイル (フォーカス)" ++ ++#~ msgid "" ++#~ "Style of the running indicator for the icon for the currently focused " ++#~ "application" ++#~ msgstr "" ++#~ "現在フォーカスがあるアプリケーションのアイコンの実行中インジケーターのスタ" ++#~ "イル" ++ ++#~ msgid "Style of the running indicator (unfocused)" ++#~ msgstr "実行中インジケーターのスタイル (非フォーカス)" ++ ++#~ msgid "" ++#~ "Style of the running indicator for the icon for applications which are " ++#~ "not currently focused" ++#~ msgstr "" ++#~ "現在フォーカスがないアプリケーションのアイコンの実行中インジケーターのスタ" ++#~ "イル" +diff --git a/po/kk.po b/po/kk.po +index 95590295..71f17c47 100644 +--- a/po/kk.po ++++ b/po/kk.po +@@ -352,6 +352,578 @@ msgstr "Атауы" + msgid "Workspace %d" + msgstr "Жұмыс орны %d" + ++#: prefs.js:295 ++msgid "Running Indicator Options" ++msgstr "Орындалып тұрған индикатор баптаулары" ++ ++#: prefs.js:302 prefs.js:447 prefs.js:499 prefs.js:608 prefs.js:684 ++#: prefs.js:753 prefs.js:829 prefs.js:871 ++msgid "Reset to defaults" ++msgstr "Бастапқы мәндерге тастау" ++ ++#: prefs.js:440 ++msgid "Show Desktop options" ++msgstr "Жұмыс үстел баптауларын көрсету" ++ ++#: prefs.js:492 ++msgid "Window preview options" ++msgstr "Терезе кіші көрінісі баптаулары" ++ ++#: prefs.js:601 ++msgid "Ungrouped application options" ++msgstr "Топталмаған қолданба баптаулары" ++ ++#: prefs.js:677 ++msgid "Customize middle-click behavior" ++msgstr "Орта шерту әрекетін баптау" ++ ++#: prefs.js:746 ++msgid "Advanced hotkeys options" ++msgstr "Кеңейтілген жарлық баптаулары" ++ ++#: prefs.js:822 ++msgid "Secondary Menu Options" ++msgstr "Қосымша мәзір баптаулары" ++ ++#: prefs.js:864 Settings.ui.h:113 ++msgid "Advanced Options" ++msgstr "Кеңейтілген баптаулар" ++ ++#: appIcons.js:1179 ++msgid "Show Details" ++msgstr "Ақпаратын көрсету" ++ ++#: appIcons.js:1198 ++msgid "New Window" ++msgstr "Жаңа терезе" ++ ++#: appIcons.js:1198 appIcons.js:1260 appIcons.js:1262 Settings.ui.h:8 ++msgid "Quit" ++msgstr "Шығу" ++ ++#: appIcons.js:1262 ++msgid "Windows" ++msgstr "Терезелер" ++ ++#: appIcons.js:1421 ++msgid "Dash to Panel Settings" ++msgstr "Dash to Panel баптаулары" ++ ++#: appIcons.js:1428 ++msgid "Restore Windows" ++msgstr "Терезелерді қалпына келтіру" ++ ++#: appIcons.js:1428 ++msgid "Show Desktop" ++msgstr "Жұмыс үстелді көрсету" ++ ++#: Settings.ui.h:1 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Қайыруға орнатылған кезде, қос шерту нәтижесінде қолданбаның барлық " ++"терезелерін қайырады." ++ ++#: Settings.ui.h:2 ++msgid "Shift+Click action" ++msgstr "Shift+Click әрекеті" ++ ++#: Settings.ui.h:3 ++msgid "Raise window" ++msgstr "Терезені көтеру" ++ ++#: Settings.ui.h:4 ++msgid "Minimize window" ++msgstr "Терезені минималды қылу" ++ ++#: Settings.ui.h:5 ++msgid "Launch new instance" ++msgstr "Жаңа экземплярды жөнелту" ++ ++#: Settings.ui.h:6 ++msgid "Cycle through windows" ++msgstr "Терезелер арасында циклмен ауысу" ++ ++#: Settings.ui.h:7 ++msgid "Cycle windows + minimize" ++msgstr "Терезелер арасында циклмен ауысу + қайыру" ++ ++#: Settings.ui.h:9 ++msgid "Behavior for Middle-Click." ++msgstr "Орта батырманың мінез-құлығы." ++ ++#: Settings.ui.h:10 ++msgid "Middle-Click action" ++msgstr "Орта батырма әрекеті" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Shift+Орта батырманың мінез-құлығы." ++ ++#: Settings.ui.h:12 ++msgid "Shift+Middle-Click action" ++msgstr "Shift+Орта батырма әрекеті" ++ ++#: Settings.ui.h:13 ++msgid "Integrate AppMenu items" ++msgstr "Қолданбалар мәзірі нәрселерін интеграциялау" ++ ++#: Settings.ui.h:14 ++msgid "Show Details menu item" ++msgstr "Ақпаратын көрсету мәзір элементі" ++ ++#: Settings.ui.h:15 ++msgid "Highlight focused application" ++msgstr "Фокустағы қолданбаларды түспен ерекшелеу" ++ ++#: Settings.ui.h:16 ++msgid "Highlight color" ++msgstr "Ерекшелеу түсі" ++ ++#: Settings.ui.h:17 ++msgid "Highlight opacity" ++msgstr "Ерекшелеудің мөлдірсіздігі" ++ ++#: Settings.ui.h:18 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:19 ++msgid "Indicator height (px)" ++msgstr "Индикатор биіктігі (пикс)" ++ ++#: Settings.ui.h:20 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:21 ++msgid "Indicator color - Override Theme" ++msgstr "Индикатор түсі - теманы үстінен басу" ++ ++#: Settings.ui.h:22 ++msgid "1 window open (or ungrouped)" ++msgstr "1 терезе ашық (немесе топталмаған)" ++ ++#: Settings.ui.h:23 ++msgid "Apply to all" ++msgstr "Барлығы үшін іске асыру" ++ ++#: Settings.ui.h:24 ++msgid "2 windows open" ++msgstr "2 терезе ашық" ++ ++#: Settings.ui.h:25 ++msgid "3 windows open" ++msgstr "3 терезе ашық" ++ ++#: Settings.ui.h:26 ++msgid "4+ windows open" ++msgstr "4+ терезе ашық" ++ ++#: Settings.ui.h:27 ++msgid "Use different for unfocused" ++msgstr "Фокустағы емес үшін басқаны қолдану" ++ ++#: Settings.ui.h:28 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Қолданба атауының қарібі (пикс, бастапқы мәні 14)" ++ ++#: Settings.ui.h:29 ++msgid "Font color of the application titles" ++msgstr "Қолданба атауының қаріп түсі" ++ ++#: Settings.ui.h:30 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Қолданба атауының максималды ені (пикс, бастапқы мәні 160)" ++ ++#: Settings.ui.h:31 ++msgid "Use a fixed width for the application titles" ++msgstr "Қолданба атауы үшін біркелкі енді қолдану" ++ ++#: Settings.ui.h:32 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Қолданба атаулары үшін біркелкі енді қолдану, олардың мәтіні максималды " ++"енінен кіші болса да. Максималды мәні тұрақты ені ретінде қолданылады." ++ ++#: Settings.ui.h:33 ++msgid "Display running indicators on unfocused applications" ++msgstr "Фокустағы емес қолданбалардың орындалу индикаторын көрсету" ++ ++#: Settings.ui.h:34 ++msgid "Use the favorite icons as application launchers" ++msgstr "Таңдамалы таңбашаларды қолданба жөнелткіштері ретінде қолдану" ++ ++#: Settings.ui.h:35 ++msgid "Preview timeout on icon leave (ms)" ++msgstr "Таңбашадан кеткен кезде кіші көріністі көрсету уақыты (мс)" ++ ++#: Settings.ui.h:36 ++msgid "" ++"If set too low, the window preview of running applications may seem to close " ++"too quickly when trying to enter the popup. If set too high, the preview may " ++"linger too long when moving to an adjacent icon." ++msgstr "" ++"Мәні тым аз болса, кіші көрініске өту талабын жасау кезінде орындалып тұрған " ++"қолданбаның кіші көрінісі тым жылдам жабылуы мүмкін. Мәні тым үлкен болса, " ++"көрші таңбашаға ауысу кезінде ағымдағы кіші көрініс ұзақ уақыт бойы " ++"көрсетілуі мүмкін." ++ ++#: Settings.ui.h:37 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Көрсету алдындағы уақыт (мс) (бастапқы шамасы 100)" ++ ++#: Settings.ui.h:38 ++msgid "Enable window peeking" ++msgstr "Терезелерді анықтауды іске қосу" ++ ++#: Settings.ui.h:39 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Курсор терезенің кіші көрінісі үстінен біраз уақыт бойы өтсе, ол терезе " ++"анықталатын болады." ++ ++#: Settings.ui.h:40 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Терезені анықтауды кідіріс уақытын енгізу (мс)" ++ ++#: Settings.ui.h:41 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Терезені анықтау үшін курсор терезенің үстінен қанша уақыт бойы аялдау керек." ++ ++#: Settings.ui.h:42 ++msgid "Window peeking mode opacity" ++msgstr "Терезелерді анықтау режимінің мөлдірсіздігі" ++ ++#: Settings.ui.h:43 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"Анықталған терезеден басқаларының мөлдірсіздігі бастапқы шамасына тең болады." ++ ++#: Settings.ui.h:44 ++msgid "Middle click to close window" ++msgstr "Терезені жабу үшін орта шерту" ++ ++#: Settings.ui.h:45 ++msgid "Middle click on the preview to close the window." ++msgstr "Терезені жабу үшін кіші көріністе орта шерту." ++ ++#: Settings.ui.h:46 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:47 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:48 ++msgid "Hotkeys prefix" ++msgstr "Ыстық пернелер префиксі" ++ ++#: Settings.ui.h:49 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Ыстық пернелер Super+Сан or Super+Alt+Сан болады" ++ ++#: Settings.ui.h:50 ++msgid "Never" ++msgstr "Ешқашан" ++ ++#: Settings.ui.h:51 ++msgid "Show temporarily" ++msgstr "Уақытша көрсету" ++ ++#: Settings.ui.h:52 ++msgid "Always visible" ++msgstr "Әрқашан көрінеді" ++ ++#: Settings.ui.h:53 ++msgid "Number overlay" ++msgstr "Цифрлық оверлей" ++ ++#: Settings.ui.h:54 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Ыстық пернелерді көрсету кезінде таңбашалардың үстінен өткізгенде қолданба " ++"нөмірлерін уақытша көрсету." ++ ++#: Settings.ui.h:55 ++msgid "Hide timeout (ms)" ++msgstr "Жасыру кідірісі (мс)" ++ ++#: Settings.ui.h:56 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Оверлейді 2 секундқа көрсету үшін пернетақта жарлығы" ++ ++#: Settings.ui.h:57 ++msgid "Syntax: , , , " ++msgstr "Синтаксисі: , , , " ++ ++#: Settings.ui.h:58 ++msgid "Show Desktop button width (px)" ++msgstr "Жұмыс үстелі батырмасының (пикс)" ++ ++#: Settings.ui.h:59 ++msgid "Panel screen position" ++msgstr "Панельдің экрандағы орны" ++ ++#: Settings.ui.h:60 ++msgid "Bottom" ++msgstr "Төмен" ++ ++#: Settings.ui.h:61 ++msgid "Top" ++msgstr "Жоғары" ++ ++#: Settings.ui.h:62 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Панель өлшемі\n" ++"(бастапқы мәні 48)" ++ ++#: Settings.ui.h:64 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Қолданба таңбашасының шет өрісі\n" ++"(бастапқы мәні 8)" ++ ++#: Settings.ui.h:66 ++msgid "Running indicator position" ++msgstr "Орындалып тұрған индикатор орны" ++ ++#: Settings.ui.h:67 ++msgid "Running indicator style (Focused app)" ++msgstr "Орындалып тұрған индикатордың стилі (фокустегі қолданба)" ++ ++#: Settings.ui.h:68 ++msgid "Dots" ++msgstr "Нүктелер" ++ ++#: Settings.ui.h:69 ++msgid "Squares" ++msgstr "Шаршылар" ++ ++#: Settings.ui.h:70 ++msgid "Dashes" ++msgstr "Штрихтер" ++ ++#: Settings.ui.h:71 ++msgid "Segmented" ++msgstr "Сегменттелген" ++ ++#: Settings.ui.h:72 ++msgid "Solid" ++msgstr "Бүтін" ++ ++#: Settings.ui.h:73 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:74 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:75 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Орындалып тұрған индикатордың стилі (фокустегі емес қолданба)" ++ ++#: Settings.ui.h:76 ++msgid "Clock location" ++msgstr "Сағаттың орналасуы" ++ ++#: Settings.ui.h:77 ++msgid "Natural" ++msgstr "Табиғи" ++ ++#: Settings.ui.h:78 ++msgid "Left of status menu" ++msgstr "Қалып-күй мәзірінің сол жағы" ++ ++#: Settings.ui.h:79 ++msgid "Right of status menu" ++msgstr "Қалып-күй мәзірінің оң жағы" ++ ++#: Settings.ui.h:80 ++msgid "Taskbar position" ++msgstr "Тапсырмалар панелінің орны" ++ ++#: Settings.ui.h:81 ++msgid "Left side of panel" ++msgstr "Панельдің сол жағы" ++ ++#: Settings.ui.h:82 ++msgid "Centered in monitor" ++msgstr "Монитордың ортасында" ++ ++#: Settings.ui.h:83 ++msgid "Centered in content" ++msgstr "Құраманың ортасында" ++ ++#: Settings.ui.h:84 ++msgid "Position and Style" ++msgstr "Орны және стилі" ++ ++#: Settings.ui.h:85 ++msgid "Show favorite applications" ++msgstr "Таңдамалы қолданбаларды көрсету" ++ ++#: Settings.ui.h:86 ++msgid "Show Applications icon" ++msgstr "Қолданбалар таңбашасын көрсету" ++ ++#: Settings.ui.h:87 ++msgid "Animate Show Applications." ++msgstr "Қолданбаларды көрсету анимациясын іске қосу." ++ ++#: Settings.ui.h:88 ++msgid "Show Activities button" ++msgstr "Көрініс таңбашасын көрсету" ++ ++#: Settings.ui.h:89 ++msgid "Show Desktop button" ++msgstr "Жұмыс үстелі батырмасын көрсету" ++ ++#: Settings.ui.h:90 ++msgid "Show AppMenu button" ++msgstr "Қолданбалар мәзірі таңбашасын көрсету" ++ ++#: Settings.ui.h:91 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Кеңейтілген баптаулар (Tweak) сайманында Үстіндегі панель >Қолданбалар " ++"мәзірін көрсету іске қосылған болуы тиіс" ++ ++#: Settings.ui.h:92 ++msgid "Show window previews on hover" ++msgstr "Курсор үстінен өткен кезде, терезенің кіші көрінісін көрсету" ++ ++#: Settings.ui.h:93 ++msgid "Isolate Workspaces" ++msgstr "Жұмыс орындарын оқшаулау" ++ ++#: Settings.ui.h:94 ++msgid "Ungroup applications" ++msgstr "Қолданбаларды топтаудан босату" ++ ++#: Settings.ui.h:95 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Орындалып тұрған қолданбаның таңбашасына шерту кезіндегі мінез-құлығы." ++ ++#: Settings.ui.h:96 ++msgid "Click action" ++msgstr "Шерту әрекеті" ++ ++#: Settings.ui.h:97 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Super+(0-9) қолданбаларды белсендіру үшін жарлықтар ретінде іске қосу. " ++"Сонымен қатар, ол Shift пен Ctrl пернелерімен бірге қолданылуы мүмкін." ++ ++#: Settings.ui.h:98 ++msgid "Use hotkeys to activate apps" ++msgstr "Қолданбаларды белсендіру үшін ыстық пернелерді қолдану" ++ ++#: Settings.ui.h:99 ++msgid "Behavior" ++msgstr "Мінез-құлығы" ++ ++#: Settings.ui.h:100 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Трей қарібінің өлшемі\n" ++"(0 = теманың бастапқы өлшемі)" ++ ++#: Settings.ui.h:102 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Сол жақ аймағының қаріп өлшемі\n" ++"(0 = теманың бастапқы өлшемі)" ++ ++#: Settings.ui.h:104 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Трейдегі нәрсенің шегінісі\n" ++"(-1 = теманың бастапқы өлшемі)" ++ ++#: Settings.ui.h:106 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Қалып-күй таңбашасының шегінісі\n" ++"(-1 = теманың бастапқы өлшемі)" ++ ++#: Settings.ui.h:108 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Сол жақ аймағының шегінісі\n" ++"(-1 = теманың бастапқы өлшемі)" ++ ++#: Settings.ui.h:110 ++msgid "Animate switching applications" ++msgstr "Қолданбаларды ауыстыру анимациясын іске қосу" ++ ++#: Settings.ui.h:111 ++msgid "Animate launching new windows" ++msgstr "Қолданбаларды жөнелту анимациясын іске қосу" ++ ++#: Settings.ui.h:112 ++msgid "App icon secondary (right-click) menu" ++msgstr "Қолданба таңбашысының қосалқы (оң жақпен шерту) мәзірі" ++ ++#: Settings.ui.h:114 ++msgid "Fine-Tune" ++msgstr "Дәлдеп баптау" ++ ++#: Settings.ui.h:115 ++msgid "version: " ++msgstr "нұсқасы: " ++ ++#: Settings.ui.h:116 ++msgid "Github" ++msgstr "Github" ++ ++#: Settings.ui.h:117 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Бұл бағдарлама ЕШҚАНДАЙ КЕПІЛДЕМЕСІЗ таратылады.\n" ++"Көбірек білу үшін GNU General Public License, нұсқасы 2 немесе кейінірек " ++"қараңыз." ++ ++#: Settings.ui.h:119 ++msgid "About" ++msgstr "Осы туралы" ++ + #~ msgid "CPU" + #~ msgstr "Процессор" + +diff --git a/po/pl.po b/po/pl.po +index a779932a..fb5abcab 100644 +--- a/po/pl.po ++++ b/po/pl.po +@@ -471,7 +471,7 @@ msgstr "Zmień tło…" + msgid "Display Settings" + msgstr "Ustawienia ekranu" + +-#: desktopGrid.js:335 ++#: desktopGrid.js:335 appIcons.js:1726 + msgid "Settings" + msgstr "Ustawienia" + +@@ -554,3 +554,1292 @@ msgstr "Kosz" + #: schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml:22 + msgid "Show the trash icon in the desktop." + msgstr "Wyświetla kosz na pulpicie." ++ ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Góra, ikony wtyczek wyrównane do prawej" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Lewa, ikony wtyczek wyrównane do prawej" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Góra, ze stałym wyśrodkowaniem ikon wtyczek" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Lewa, ze stałym wyśrodkowaniem ikon wtyczek" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Góra, ze swobodnym wyśrodkowaniem ikon wtyczek" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Lewa, ze swobodnym wyśrodkowaniem ikon wtyczek" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Środek, ze stałym wyśrodkowaniem na monitorze" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Środek, z elementami swobodnymi między górą a dołem" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Środek, z elementami swobodnymi między lewą a prawą stroną" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Górna strona ikon wtyczek" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "Lewa strona ikon wtyczek" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Dolna strona ikon wtyczek" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "Prawa strona ikon wtyczek" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Górna strona menu systemowego" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "Lewa strona menu systemowego" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Dolna strona menu systemowego" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "Prawa strona menu systemowego" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Górna strona paska zadań" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "Lewa strona paska zadań" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Dolna strona paska zadań" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "Prawa strona paska zadań" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Wysokość przycisku Pokaż pulpit (px)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Szerokość przycisku Pokaż pulpit (px)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Opcje wskaźnika aktywnych programów" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "Przywróć domyślne" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Domyślny (Główny monitor)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Monitor " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Opcje wielu monitorów" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Opcje dynamicznej przeźroczystości" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Opcje inteligentnego ukrywania" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Opcje wyświetlania programów" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Pokaż opcje pulpitu" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "Opcje podglądu okna" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "Opcje trybu listy" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "Dostosuj działanie środkowego przycisku myszy" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "Dostosuj reakcję na przewijanie panelu" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "Dostosuj reakcję na przewijanie po ikonach" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "Zaawansowane opcje skrótów klawiszowych" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "Opcje menu kontekstowego" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "Opcje zaawansowane" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "Eksportuj ustawienia" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "Importuj ustawienia" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "Pokaż szczegóły" ++ ++#: appIcons.js:1398 ++msgid "New Window" ++msgstr "Nowe okno" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Zamknięcie okna" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "Okna" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "Opcje zasilania" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "Zapis zdarzeń" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "System" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "Zarządzanie urządzeniami" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "Zarządzanie dyskami" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "Terminal" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "Monitor procesów" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "Pliki" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "Odblokuj pasek zadań" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "Zablokuj pasek zadań" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "Ustawienia Dash to Panel" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "Przywróć okna" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "Pokaż pulpit" ++ ++#: update.js:58 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "Wersja %s (%s) jest dostępna" ++ ++#: update.js:59 ++msgid "Details" ++msgstr "Szczegóły" ++ ++#: update.js:60 ++msgid "Update" ++msgstr "Aktualizacja" ++ ++#: update.js:63 ++msgid "Already up to date" ++msgstr "Brak nowszej wersji" ++ ++#: update.js:148 ++msgid "Update successful, please log out/in" ++msgstr "Aktualizacja zakończona pomyślnie, zaloguj się ponownie" ++ ++#: update.js:149 ++msgid "Log out" ++msgstr "Wyloguj" ++ ++#: update.js:153 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Aktualizacja zakończona pomyślnie, prosimy zrestartować powłokę GNOME" ++ ++#: update.js:154 ++msgid "Restart GNOME Shell" ++msgstr "Zrestartuj powłokę GNOME" ++ ++#: update.js:154 ++msgid "Restarting GNOME Shell..." ++msgstr "Restartowanie powłoki GNOME..." ++ ++#: update.js:160 ++msgid "Error: " ++msgstr "Błąd: " ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Jeszcze nic!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Wybranie zminimalizowania okna umożliwia minimalizowanie wszystkich okien " ++"programu dwukrotnym kliknięciem." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Kliknięcie lewym przyciskiem + Shift" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Przywróć okna" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Zminimalizowanie okna" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Uruchomienie nowego okna" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Przełączanie między oknami" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Przełączanie + zminimalizowanie okien" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Przełącz pojedyncze / Podejrzyj wiele" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Konfiguruje działanie kliknięcia środkowym przyciskiem." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Akcja środkowego przycisku" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "" ++"Konfiguruje działanie kliknięcia środkowym przyciskiem z przytrzymanym " ++"klawiszem Shift." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Kliknięcie środkowym przyciskiem + Shift" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Niezależne obszary robocze" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Ulubione programy na wszystkich monitorach" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Zegar na wszystkich monitorach" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Menu systemowe na wszystkich monitorach" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Zintegruj elementy menu programów" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Wyświetl szczegóły" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Podświetlaj ikonę aktywnego programu" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Dominujący kolor ikon" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Własny kolor" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Przeźroczystość podświetlenia" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "Wysokość wskaźnika (px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Kolor wskaźnika - dominujący" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Kolor wskaźnika - nadpisanie motywu" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 otwarte okno (lub tryb listy)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Zastosuj do wszystkich" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 otwarte okna" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 otwarte okna" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4 i więcej otwartych okien" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Użyj innego dla pozostałych" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Wielkość czcionki etykiet (px) (domyślnie 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Grubość czcionki tytułów programów" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "dziedzicz po motywie" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "zwykła" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "cieńsza" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "pogrubiona" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "grubsza" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Kolor czcionki" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Maksymalna szerokość (px) etykiet (domyślnie 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Stała szerokości" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Wszystkie etykiety ikon będą miały tę samą szerokość, nawet jeśli ich teksty " ++"są krótsze niż maksymalna szerokość. Wartość stałej szerokości jest taka, " ++"jaka została podana w polu Maksymalna szerokość." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Pokazuj wskaźnik dla otwartych okien drugoplanowych" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Oddziel ulubione od uruchomionych programów" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Ukryj panel tylko wtedy, gdy jest zasłonięty przez okna " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "Ukrywanie przed oknami" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Wszystkie okna" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Aktywne okna programu" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Zmaksymalizowane okna" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Wymagaj nacisku na krawędzi ekranu, aby odsłonić panel" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Próg nacisku (px)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Czas nacisku (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Pozwól, aby panel został odsłonięty w trybie pełnoekranowym" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Ukryj wyłącznie drugorzędne panele (dla wielu monitorów)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "np. i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Skrót klawiszowy do ukrywania i odsłaniania panelu" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Składnia: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Czas trwania animacji ukrywania i odsłaniania (ms)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Opóźnienie ukrycia panelu (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Opóźnienie przed aktywacją inteligentnego ukrywania (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Opóźnienie (ms) przed pokazaniem (domyślnie 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Długość animacji (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Opóźnienie ukrywania miniatur (domyślnie 100 ms)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Natychmiastowo po kliknięciu na ikonę aplikacji" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "" ++"Kliknięcie środkowego przycisku myszy na podglądzie zamyka okno programu" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Preferowany rozmiar podglądu okna (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Proporcja wysokości podglądu okna" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Wewnętrzny odstęp w podglądzie okien (px)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Stałe" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Proporcja szerokości podglądu okna" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Własna przeźroczystość dla tła podglądu okna" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Jeśli wyłączone, podgląd okna będzie mieć taką samą przeźroczystość jak panel" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Położenie przycisku zamykania i nagłówka" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Dół" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Góra" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Wyświetlaj nagłówek w podglądzie okna" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Wielkość czcionki etykiet (px) etykiet podglądu" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Grubość czcionki etykiet podglądu" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Kolor czcionki etykiet podglądu" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Podgląd okien otwartych programów" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Po najechaniu kursorem na podgląd okna zostanie ono pokazane na tle " ++"wszystkich otwartych okien programów." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Opóźnienie wyświetlania (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Czas opóźnienia, po którym wyświetlony zostanie podgląd okien otwartych " ++"programów." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Przeźroczystość podglądanych okien" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"Wszystkie okna, za wyjątkiem okna głównego, mają tą samą przeźroczystość." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Opóźnienie między przewijaniem myszą (ms)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "Użyj tą wartość by ograniczyć liczbę przechwyceń przewijania myszą." ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Prefiks dla skrótów klawiszowych" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Skrót może być aktywowany jako Super+Cyfra lub Super+Alt+Cyfra" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Nigdy" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Przez chwilę" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Zawsze" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Pokazywanie cyfr" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "Podczas używania skrótów klawiszowych wyświetlaj cyfry nad ikonami ." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Opóźnienie ukrywania (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "np. q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Skrót wyświetlający cyfry przez 2 sekundy" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Pokaż podgląd okna po wciśnięciu klawisza skrótu" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Pokaż podgląd, gdy aplikacja ma wiele instancji" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Rząd cyfr" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Klawiatura numeryczna" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Obie" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Aktywacja skrótów klawiszowych wymaga" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Zaznacz które klawisze cyfr mają być używane do aktywacji skrótów " ++"klawiszowych" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Aktualna ikona przycisku Pokaż programy" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Wybierz ikonę przycisku Pokaż programy" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Wybierz własną ikonę przycisku Pokaż programy" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Wewnętrzny margines przycisku Pokaż programy (px)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Pokaż pulpit po najechaniu na przycisk Pokaż pulpit" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Opóźnienie przed ujawnieniem pulpitu (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Opóźnienie ukrywania (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "Przezroczystość panelu zależy od" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Zmień przezroczystość, gdy okno jest bliżej niż (px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Zmień przeźroczystość na (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Czas trwania animacji przeźroczystości (ms)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Położenie panelu na ekranie" ++ ++#: Settings.ui.h:145 ++msgid "Left" ++msgstr "Lewo" ++ ++#: Settings.ui.h:146 ++msgid "Right" ++msgstr "Prawo" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Położenie paska zadań" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Położenie zegara" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Wyświetl główny panel na" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Wyświetl panel na wszystkich monitorach" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Inteligentne ukrywanie panelu" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Ukryj i odsłoń panel według preferencji" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Położenie" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Rozmiar panelu\n" ++"(domyślnie 48)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Odstęp między\n" ++"ikonami (domyślnie 8)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Wypełnienie wnętrza\n" ++"ikony (domyślnie 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Pozycja wskaźnika aktywnych okien" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Wygląd wskaźnika (okno na pierwszym planie)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Kropki" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Kwadraty" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Kreski" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Segmenty" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Ciągły" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Wygląd wskaźnika (okno na drugim planie)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Zastąp kolor panelu " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Zastąp przeźroczystość panelu" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Przeźroczystość panelu (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Dynamiczna przeźroczystość" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Zmiana przeźroczystości w kontakcie z oknem" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Zastąp kolor panelu gradientem " ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Góra, kolor i przeźroczystość (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Dół, kolor i przeźroczystość (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Wygląd" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Pokaż ulubione programy" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Pokaż uruchomione programy" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Pokaż ikonę Programy" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Animuj pokazanie programów." ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Pokaż przycisk Podgląd" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Pokaż przycisk Pulpit" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Pokaż przycisk Menu programu" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "Górny pasek > Menu programu - musi być włączone w Dostrajanie" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Pokaż podgląd okna po najechaniu myszą" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Pokaż szczegóły po najechaniu myszą" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Niezależne obszary robocze" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Tryb listy (nie scalaj ikon)" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Reakcja" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Reakcja na kliknięcie ikony aktywnego programu." ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Działanie kliknięcia" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Przełącz okna" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Działanie przewijania na panelu" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Reakcja na przewijanie myszą nad panelem." ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Działanie przewijania na ikonie" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Reakcja na przewijanie myszą nad ikoną programu." ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Nic nie rób" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Przełącz ekran roboczy" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Przełącz między oknami" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Konfigurowanie skrótów uruchamiania programów\n" ++"Super+(0-9) - możliwe użycie razem z Shift i Ctrl." ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "Skróty klawiszowe uruchamiania programów" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "Działanie" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Rozmiar czcionki zasobnika\n" ++"(0 - domyślne motywu)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Rozmiar czcionki lewej strony panelu\n" ++"(0 - domyślne motywu)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Odstęp elementów zasobnika\n" ++"(-1 - domyślne motywu)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Odstęp elementów menu systemowego\n" ++"(-1 - domyślne motywu)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Odstęp elementów lewej strony panelu\n" ++"(-1 - domyślne motywu)" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "Animuj przełączenie programów" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "Animuj uruchamianie nowych programów" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Zachowaj oryginalny panel (podgląd)" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "" ++"Aktywuj przyciski menu panelu (np. menu kalendarza) tylko po kliknięciu" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "Menu kontekstowe programu (prawy przycisk myszy)" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "Dostrajanie" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "wersja: " ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Użyj poniższych przycisków, aby utworzyć plik ustawień bieżącychpreferencji, " ++"które można zaimportować na innym komputerze." ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "Ustawienia eksportu i importu" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "Eksportuj do pliku" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "Importuj z pliku" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Ta opcja pozwala ci na zaktualizowanie wtyczki bezpośrednio z repozytorium " ++"GitHub." ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "Aktualizacje" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "Sprawdzaj regularnie dostępność aktualizacji" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "Sprawdź teraz" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Bądź świadom, że te oficjalne " ++"wydania Dash to Panel mogły jeszcze nie przejść weryfikacji na extensions." ++"gnome.org! Więcej " ++"informacji" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Tego programu nie obejmuje ABSOLUTNIE ŻADNA GWARANCJA.\n" ++"Więcej informacji można znaleźć w licencji GNU General Public License, wersja 2 " ++"lub nowsza." ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "Informacje" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Kolor podświetlenia" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Opóźnienie wygaszenia podglądu po opuszczeniu ikony (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Ustawienie zbyt małej wartości może spowodować, że pogląd okien może " ++#~ "zamykać się zbyt szybko, natomiast za duża wartość spowoduje długi czas " ++#~ "wyświetlania podglądu po przejściu do sąsiedniej ikony." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Zamknięcie okna poprzez kliknięcie środkowego przycisku" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Szerokość miniatury (px)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Wysokość miniatury (px)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Odstęp między miniaturami (px)" +diff --git a/po/pt_BR.po b/po/pt_BR.po +index f1e17f73..3f1ac914 100644 +--- a/po/pt_BR.po ++++ b/po/pt_BR.po +@@ -567,6 +567,438 @@ msgstr "Mostrar ícone da lixeira" + msgid "Show the trash icon in the desktop." + msgstr "Mostra o ícone da lixeira na área de trabalho." + ++#: appIcons.js:937 ++msgid "New Window" ++msgstr "Nova janela" ++ ++#: appIcons.js:918 ++msgid "Show Details" ++msgstr "Exibir detalhes" ++ ++#: appIcons.js:937 appIcons.js:998 appIcons.js:1000 Settings.ui.h:8 ++msgid "Quit" ++msgstr "Sair" ++ ++#: appIcons.js:1000 ++msgid "Windows" ++msgstr "Janelas" ++ ++#: appIcons.js:1159 ++msgid "Dash to Panel Settings" ++msgstr "Configurações do Dash to Panel" ++ ++#: appIcons.js:1166 ++msgid "Restore Windows" ++msgstr "Restaurar janelas" ++ ++#: appIcons.js:1166 ++msgid "Show Desktop" ++msgstr "Exibir área de trabalho" ++ ++#: prefs.js:266 ++msgid "Running Indicator Options" ++msgstr "Opções do indicador de execução" ++ ++#: prefs.js:273 prefs.js:433 prefs.js:498 prefs.js:566 prefs.js:608 ++msgid "Reset to defaults" ++msgstr "Restaurar o padrão" ++ ++#: prefs.js:426 ++msgid "Customize middle-click behavior" ++msgstr "Personalizar o comportamento do clique-do-meio" ++ ++#: prefs.js:491 ++msgid "Advanced hotkeys options" ++msgstr "Opções avançadas das teclas de atalho" ++ ++#: prefs.js:559 ++msgid "Secondary Menu Options" ++msgstr "Opções do menu secundário" ++ ++#: prefs.js:601 Settings.ui.h:85 ++msgid "Advanced Options" ++msgstr "Opções avançadas" ++ ++#: Settings.ui.h:1 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Quando definido para minimizar, clicando duas vezes minimiza todas as " ++"janelas da aplicação." ++ ++#: Settings.ui.h:2 ++msgid "Shift+Click action" ++msgstr "Ação do Shift+clique" ++ ++#: Settings.ui.h:3 ++msgid "Raise window" ++msgstr "Elevar a janela" ++ ++#: Settings.ui.h:4 ++msgid "Minimize window" ++msgstr "Minimizar a janela" ++ ++#: Settings.ui.h:5 ++msgid "Launch new instance" ++msgstr "Carregar nova instância" ++ ++#: Settings.ui.h:6 ++msgid "Cycle through windows" ++msgstr "Percorrer as janelas" ++ ++#: Settings.ui.h:7 ++msgid "Cycle windows + minimize" ++msgstr "Ciclo de janelas + minimizar" ++ ++#: Settings.ui.h:9 ++msgid "Behavior for Middle-Click." ++msgstr "Comportamento do clique-do-meio." ++ ++#: Settings.ui.h:10 ++msgid "Middle-Click action" ++msgstr "Ação do clique-do-meio" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Comportamento para o Shift+Clique-do-meio." ++ ++#: Settings.ui.h:12 ++msgid "Shift+Middle-Click action" ++msgstr "Ação do Shift+Clique-do-meio" ++ ++#: Settings.ui.h:13 ++msgid "Integrate AppMenu items" ++msgstr "Itens integrados ao Menu de aplicativos" ++ ++#: Settings.ui.h:14 ++msgid "Show Details menu item" ++msgstr "Item do menu Exibir detalhes" ++ ++#: Settings.ui.h:15 ++msgid "Highlight focused application" ++msgstr "Destaque para o aplicativo em foco" ++ ++#: Settings.ui.h:16 ++msgid "Height (px)" ++msgstr "Altura (px)" ++ ++#: Settings.ui.h:17 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:18 ++msgid "Color - Override Theme" ++msgstr "Cor - Tema de sobreposição" ++ ++#: Settings.ui.h:19 ++msgid "1 window open" ++msgstr "1 janela aberta" ++ ++#: Settings.ui.h:20 ++msgid "Apply to all" ++msgstr "Aplicar para tudo" ++ ++#: Settings.ui.h:21 ++msgid "2 windows open" ++msgstr "2 janelas abertas" ++ ++#: Settings.ui.h:22 ++msgid "3 windows open" ++msgstr "3 janelas abertas" ++ ++#: Settings.ui.h:23 ++msgid "4+ windows open" ++msgstr "4 ou + janelas abertas" ++ ++#: Settings.ui.h:24 ++msgid "Use different for unfocused" ++msgstr "Utilizar uma diferente para o que não está focado" ++ ++#: Settings.ui.h:25 ++msgid "Preview timeout on icon leave (ms)" ++msgstr "Tempo limite de pré-visualização sobre o ícone sair (ms)" ++ ++#: Settings.ui.h:26 ++msgid "" ++"If set too low, the window preview of running applications may seem to close " ++"too quickly when trying to enter the popup. If set too high, the preview may " ++"linger too long when moving to an adjacent icon." ++msgstr "" ++"Se definido como muito baixo, a pré-visualização da janela de aplicativos em " ++"execução pode fechar muito rapidamente ao tentar inserir o pop-up. Se " ++"definido como muito alto, a visualização pode demorar muito tempo ao mover-" ++"se para um ícone adjacente." ++ ++#: Settings.ui.h:27 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:28 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:29 ++msgid "Hotkeys prefix" ++msgstr "Prefixo das teclas de atalho" ++ ++#: Settings.ui.h:30 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "As teclas de atalho serão Super+Número ou Super+Alt+Número" ++ ++#: Settings.ui.h:31 ++msgid "Number overlay" ++msgstr "Sobreposição de número" ++ ++#: Settings.ui.h:32 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Exibe temporariamente os números das aplicações sobre os ícones ao usar as " ++"teclas de atalho." ++ ++#: Settings.ui.h:33 ++msgid "Hide timeout (ms)" ++msgstr "Ocultar tempo limite (ms)" ++ ++#: Settings.ui.h:34 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Atalho para exibir a sobreposição por 2 segundos" ++ ++#: Settings.ui.h:35 ++msgid "Syntax: , , , " ++msgstr "Sintaxe: , , , " ++ ++#: Settings.ui.h:36 ++msgid "Panel screen position" ++msgstr "Posição da tela do painel" ++ ++#: Settings.ui.h:37 ++msgid "Bottom" ++msgstr "Embaixo" ++ ++#: Settings.ui.h:38 ++msgid "Top" ++msgstr "Topo" ++ ++#: Settings.ui.h:39 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Tamanho do painel\n" ++"(O padrão é 48)" ++ ++#: Settings.ui.h:41 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Margem do ícone do Aplicativo\n" ++"(O padrão é 8)" ++ ++#: Settings.ui.h:43 ++msgid "Running indicator position" ++msgstr "Posição do indicador de execução" ++ ++#: Settings.ui.h:44 ++msgid "Running indicator style (Focused app)" ++msgstr "Estilo do indicador de execução (Aplicativo em foco)" ++ ++#: Settings.ui.h:45 ++msgid "Dots" ++msgstr "Pontos" ++ ++#: Settings.ui.h:46 ++msgid "Squares" ++msgstr "Quadrados" ++ ++#: Settings.ui.h:47 ++msgid "Dashes" ++msgstr "Traços" ++ ++#: Settings.ui.h:48 ++msgid "Segmented" ++msgstr "Segmentado" ++ ++#: Settings.ui.h:49 ++msgid "Solid" ++msgstr "Sólido" ++ ++#: Settings.ui.h:50 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:51 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:52 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Estilo do indicador de execução (Aplicativos fora de foco)" ++ ++#: Settings.ui.h:53 ++msgid "Clock location" ++msgstr "Local do relógio" ++ ++#: Settings.ui.h:54 ++msgid "Natural" ++msgstr "Natural" ++ ++#: Settings.ui.h:55 ++msgid "Left of status menu" ++msgstr "Esquerda do menu de status" ++ ++#: Settings.ui.h:56 ++msgid "Right of status menu" ++msgstr "Direita do menu de status" ++ ++#: Settings.ui.h:57 ++msgid "Position and Style" ++msgstr "Posição e Estilo" ++ ++#: Settings.ui.h:58 ++msgid "Show Applications icon" ++msgstr "Mostrar ícone Aplicativos" ++ ++#: Settings.ui.h:59 ++msgid "Animate Show Applications." ++msgstr "Mostrar aplicativos animado." ++ ++#: Settings.ui.h:60 ++msgid "Show Activities button" ++msgstr "Mostrar botão Atividades" ++ ++#: Settings.ui.h:61 ++msgid "Show Desktop button" ++msgstr "Mostrar botão Área de trabalho" ++ ++#: Settings.ui.h:62 ++msgid "Show AppMenu button" ++msgstr "Mostrar botão Menu de aplicativos" ++ ++#: Settings.ui.h:63 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Barra superior > Mostrar o Menu do aplicativos deve ser ativado na " ++"Ferramenta de ajustes do GNOME" ++ ++#: Settings.ui.h:64 ++msgid "Show window previews on hover" ++msgstr "Mostrar pré-visulização da janela ao pairar" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Tempo (ms) antes de exibir (100 é o padrão)" ++ ++#: Settings.ui.h:66 ++msgid "Isolate Workspaces" ++msgstr "Isolar Espaços de trabalho" ++ ++#: Settings.ui.h:67 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Comportamento ao clicar sobre o ícone de um aplicativo em execução." ++ ++#: Settings.ui.h:68 ++msgid "Click action" ++msgstr "Ação do clique" ++ ++#: Settings.ui.h:69 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Habilita o Super+(0-9) como atalho para os aplicativos. Isto pode ser usado " ++"junto com Shift e Ctrl." ++ ++#: Settings.ui.h:70 ++msgid "Use hotkeys to activate apps" ++msgstr "Utilziar teclas de atalho para ativar os aplicativos" ++ ++#: Settings.ui.h:71 ++msgid "Behavior" ++msgstr "Comportamento" ++ ++#: Settings.ui.h:72 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tamanho da fonte da bandeja\n" ++"(0 = padrão do tema)" ++ ++#: Settings.ui.h:74 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Tamanho da fonte da caixa da esquerda\n" ++"(0 = padrão do tema)" ++ ++#: Settings.ui.h:76 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Preenchimento do ítem da bandeja\n" ++"(-1 = padrão do tema)" ++ ++#: Settings.ui.h:78 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Preenchimento do ícone de status\n" ++"(-1 = padrão do tema)" ++ ++#: Settings.ui.h:80 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Preenchimento da caixa da esquerda\n" ++"(-1 = padrão do tema)" ++ ++#: Settings.ui.h:82 ++msgid "Animate switching applications" ++msgstr "Animar alternações dos aplicativos" ++ ++#: Settings.ui.h:83 ++msgid "Animate launching new windows" ++msgstr "Carregamento animado de novas janelas" ++ ++#: Settings.ui.h:84 ++msgid "App icon secondary (right-click) menu" ++msgstr "Ícone do aplicativo do menu secundário (clique-direito)" ++ ++#: Settings.ui.h:86 ++msgid "Fine-Tune" ++msgstr "Sintonia fina" ++ ++#: Settings.ui.h:87 ++msgid "version: " ++msgstr "versão: " ++ ++#: Settings.ui.h:88 ++msgid "Github" ++msgstr "Github" ++ ++#: Settings.ui.h:89 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Este programa vem com ABSOLUTAMENTE NENHUMA GARANTIA.\n" ++"Veja a Licença Pública Geral GNU, versão 2 ou posterior para maiores " ++"detalhes." ++ ++#: Settings.ui.h:91 ++msgid "About" ++msgstr "Sobre" ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -630,9 +1062,6 @@ msgstr "Mostra o ícone da lixeira na área de trabalho." + #~ msgid "Drag here to add favorites" + #~ msgstr "Arraste aqui para adicionar favoritos" + +-#~ msgid "New Window" +-#~ msgstr "Nova janela" +- + #~ msgid "Quit Application" + #~ msgstr "Fechar aplicativo" + +@@ -837,3 +1266,9 @@ msgstr "Mostra o ícone da lixeira na área de trabalho." + + #~ msgid "Ok" + #~ msgstr "Ok" ++ ++#~ msgid "Panel Size" ++#~ msgstr "Tamanho do painel" ++ ++#~ msgid "Appearance" ++#~ msgstr "Aparência" +diff --git a/po/ru.po b/po/ru.po +index 9320c3ca..95e278af 100644 +--- a/po/ru.po ++++ b/po/ru.po +@@ -445,8 +445,13 @@ msgid "Display Settings" + msgstr "Настройки дисплея" + + #: desktopGrid.js:315 ++#, fuzzy + msgid "Settings" +-msgstr "Параметры" ++msgstr "" ++"#-#-#-#-# ru.po (gnome-shell-extensions gnome-3-0) #-#-#-#-#\n" ++"Параметры\n" ++"#-#-#-#-# ru.po #-#-#-#-#\n" ++"Настройки" + + #: desktopGrid.js:569 + msgid "Enter file name…" +@@ -516,6 +521,1261 @@ msgstr "Показывать значок корзины" + msgid "Show the trash icon in the desktop." + msgstr "Показывать значок корзины на рабочем столе." + ++#: prefs.js:206 ++msgid "Show Desktop button height (px)" ++msgstr "Высота кнопки \"Рабочий стол\" (в пикселях)" ++ ++#: prefs.js:206 ++msgid "Show Desktop button width (px)" ++msgstr "Ширина кнопки \"Рабочий стол\" (в пикселях)" ++ ++#: prefs.js:218 ++msgid "Unavailable when gnome-shell top panel is present" ++msgstr "Недоступно, если включена верхняя панель GNOME" ++ ++#: prefs.js:293 ++msgid "Show Applications button" ++msgstr "Кнопка \"Приложения\"" ++ ++#: prefs.js:294 ++msgid "Activities button" ++msgstr "Кнопка \"Обзор\"" ++ ++#: prefs.js:295 ++msgid "Taskbar" ++msgstr "Панель задач" ++ ++#: prefs.js:296 ++msgid "Date menu" ++msgstr "Дата и время" ++ ++#: prefs.js:297 ++msgid "System menu" ++msgstr "Системное меню" ++ ++#: prefs.js:298 ++msgid "Left box" ++msgstr "Левый блок" ++ ++#: prefs.js:299 ++msgid "Center box" ++msgstr "Центральный блок" ++ ++#: prefs.js:300 ++msgid "Right box" ++msgstr "Правый блок" ++ ++#: prefs.js:301 ++msgid "Desktop button" ++msgstr "Кнопка \"Рабочий стол\"" ++ ++#: prefs.js:307 ++msgid "Move up" ++msgstr "Переместить выше" ++ ++#: prefs.js:309 ++msgid "Move down" ++msgstr "Переместить ниже" ++ ++#: prefs.js:311 ++msgid "Visible" ++msgstr "Видимый" ++ ++#: prefs.js:312 ++msgid "Select element position" ++msgstr "Выбор позиции элемента" ++ ++#: prefs.js:323 ++msgid "Stacked to top" ++msgstr "Сверху" ++ ++#: prefs.js:323 ++msgid "Stacked to left" ++msgstr "Слева" ++ ++#: prefs.js:324 ++msgid "Stacked to bottom" ++msgstr "Снизу" ++ ++#: prefs.js:324 ++msgid "Stacked to right" ++msgstr "Справа" ++ ++#: prefs.js:325 ++msgid "Centered" ++msgstr "По центру" ++ ++#: prefs.js:326 ++msgid "Monitor Center" ++msgstr "Центр монитора" ++ ++#: prefs.js:345 ++msgid "More options" ++msgstr "Дополнительные параметры" ++ ++#: prefs.js:369 ++msgid "Show Applications options" ++msgstr "Настройка меню \"Приложения\"" ++ ++#: prefs.js:376 prefs.js:433 prefs.js:576 prefs.js:894 prefs.js:1037 ++#: prefs.js:1164 prefs.js:1450 prefs.js:1545 prefs.js:1610 prefs.js:1653 ++#: prefs.js:1750 prefs.js:1784 prefs.js:1826 ++msgid "Reset to defaults" ++msgstr "По умолчанию" ++ ++#: prefs.js:426 ++msgid "Show Desktop options" ++msgstr "Настройки кнопки \"Рабочий стол\"" ++ ++#: prefs.js:569 ++msgid "Running Indicator Options" ++msgstr "Параметры индикации запущенных приложений" ++ ++#: prefs.js:732 ++msgid "Primary monitor" ++msgstr "Основной монитор" ++ ++#: prefs.js:732 ++msgid "Monitor " ++msgstr "Монитор " ++ ++#: prefs.js:887 ++msgid "Dynamic opacity options" ++msgstr "Настройки динамической прозрачности" ++ ++#: prefs.js:1030 ++msgid "Intellihide options" ++msgstr "Настройки автоскрытия" ++ ++#: prefs.js:1157 ++msgid "Window preview options" ++msgstr "Настройки предпросмотра" ++ ++#: prefs.js:1443 ++msgid "Ungrouped application options" ++msgstr "Отображение разгруппированных приложений" ++ ++#: prefs.js:1538 ++msgid "Customize middle-click behavior" ++msgstr "Средняя кнопка мышки" ++ ++#: prefs.js:1603 ++msgid "Customize panel scroll behavior" ++msgstr "Прокручивание панелей" ++ ++#: prefs.js:1646 ++msgid "Customize icon scroll behavior" ++msgstr "Прокручивание значков" ++ ++#: prefs.js:1743 ++msgid "Advanced hotkeys options" ++msgstr "Расширенные настройки горячих клавиш" ++ ++#: prefs.js:1777 ++msgid "Secondary Menu Options" ++msgstr "Дополнительные настройки меню" ++ ++#: prefs.js:1819 Settings.ui.h:230 ++msgid "Advanced Options" ++msgstr "Расширенные настройки" ++ ++#: prefs.js:1922 ++msgid "Export settings" ++msgstr "Сохранение" ++ ++#: prefs.js:1939 ++msgid "Import settings" ++msgstr "Загрузка" ++ ++#: appIcons.js:1418 ++msgid "Show Details" ++msgstr "Показать подробности" ++ ++#: appIcons.js:1436 ++msgid "New Window" ++msgstr "Новое окно" ++ ++#: appIcons.js:1436 appIcons.js:1496 appIcons.js:1498 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Выйти" ++ ++#: appIcons.js:1498 ++msgid "Windows" ++msgstr "Окна" ++ ++#: appIcons.js:1847 ++msgid "Unlock taskbar" ++msgstr "Открепить список задач" ++ ++#: appIcons.js:1847 ++msgid "Lock taskbar" ++msgstr "Закрепить список задач" ++ ++#: appIcons.js:1852 ++msgid "Dash to Panel Settings" ++msgstr "Настройки Dash to Panel" ++ ++#: appIcons.js:1865 ++msgid "Restore Windows" ++msgstr "Восстановить окна" ++ ++#: appIcons.js:1865 ++msgid "Show Desktop" ++msgstr "Свернуть всё" ++ ++#: update.js:48 ++msgid "Unavailable when installed from extensions.gnome.org" ++msgstr "Недоступно, если установлено из extensions.gnome.org" ++ ++#: update.js:62 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "Доступна версия %s (%s)" ++ ++#: update.js:63 ++msgid "Details" ++msgstr "Подробнее" ++ ++#: update.js:64 ++msgid "Update" ++msgstr "Обновление" ++ ++#: update.js:67 ++msgid "Already up to date" ++msgstr "Обновлений нет" ++ ++#: update.js:75 ++msgid "Error: " ++msgstr "Ошибка: " ++ ++#: update.js:168 ++msgid "Update successful, please log out/in" ++msgstr "Обновление успешно, перезайдите в систему" ++ ++#: update.js:169 ++msgid "Log out" ++msgstr "Выход из системы" ++ ++#: update.js:173 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Обновление успешно, перезапустите GNOME Shell" ++ ++#: update.js:174 ++msgid "Restart GNOME Shell" ++msgstr "Перезапуск GNOME Shell" ++ ++#: update.js:174 ++msgid "Restarting GNOME Shell..." ++msgstr "Перезапускаем GNOME Shell..." ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Пока пусто!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Если выбрано \"Свернуть окно\", двойной щелчок сворачивает все окна " ++"приложения." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Действия для Shift+Щелчок" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Показать окно приложения" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Свернуть окно" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Запустить ещё одну копию" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Переключение между окнами" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Переключение между окнами + Свернуть" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Переключить одно / Просмотр нескольких" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Поведение для средней кнопки мыши." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Действие на нажатие средней кнопки" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Поведение для Shift+средняя_кнопка." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Действие на нажатие Shift+средняя_кнопка" ++ ++#: Settings.ui.h:15 ++msgid "Integrate AppMenu items" ++msgstr "Интегрировать Меню Приложения" ++ ++#: Settings.ui.h:16 ++msgid "Show Details menu item" ++msgstr "Меню Показать детали" ++ ++#: Settings.ui.h:17 ++msgid "Highlight focused application" ++msgstr "Подсвечивать приложение в фокусе" ++ ++#: Settings.ui.h:18 ++msgid "Icon dominant color" ++msgstr "Основной цвет значка" ++ ++#: Settings.ui.h:19 ++msgid "Custom color" ++msgstr "Задать цвет" ++ ++#: Settings.ui.h:20 ++msgid "Highlight opacity" ++msgstr "Прозрачность подсветки" ++ ++#: Settings.ui.h:21 ++msgid "Indicator size (px)" ++msgstr "Размер индикатора (в пикселях)" ++ ++#: Settings.ui.h:22 ++msgid "Indicator color - Icon Dominant" ++msgstr "Цвет индикатора по основному цвету значка" ++ ++#: Settings.ui.h:23 ++msgid "Indicator color - Override Theme" ++msgstr "Переназначить цвета темы" ++ ++#: Settings.ui.h:24 ++msgid "1 window open (or ungrouped)" ++msgstr "Когда одно окно открыто (или не сгруппировано)" ++ ++#: Settings.ui.h:25 ++msgid "Apply to all" ++msgstr "Применить ко всем" ++ ++#: Settings.ui.h:26 ++msgid "2 windows open" ++msgstr "Когда два окна открыто" ++ ++#: Settings.ui.h:27 ++msgid "3 windows open" ++msgstr "Когда три окна открыто" ++ ++#: Settings.ui.h:28 ++msgid "4+ windows open" ++msgstr "Когда четыре+ окна открыто" ++ ++#: Settings.ui.h:29 ++msgid "Use different for unfocused" ++msgstr "Использовать другой когда не в фокусе" ++ ++#: Settings.ui.h:30 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Размер шрифта (в пикселях) заголовка приложений (по умолчанию 14)" ++ ++#: Settings.ui.h:31 ++msgid "Font weight of application titles" ++msgstr "Жирность шрифта заголовка приложений" ++ ++#: Settings.ui.h:32 ++msgid "inherit from theme" ++msgstr "значение из темы" ++ ++#: Settings.ui.h:33 ++msgid "normal" ++msgstr "средний" ++ ++#: Settings.ui.h:34 ++msgid "lighter" ++msgstr "узкий" ++ ++#: Settings.ui.h:35 ++msgid "bold" ++msgstr "жирный" ++ ++#: Settings.ui.h:36 ++msgid "bolder" ++msgstr "самый жирный" ++ ++#: Settings.ui.h:37 ++msgid "Font color of the application titles" ++msgstr "Цвет шрифта заголовка приложений" ++ ++#: Settings.ui.h:38 ++msgid "Font color of the minimized application titles" ++msgstr "Цвет шрифта заголовка свернутых приложений" ++ ++#: Settings.ui.h:39 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "" ++"Максимальная ширина (в пикселях) заголовка приложений (по умолчанию 160)" ++ ++#: Settings.ui.h:40 ++msgid "Use a fixed width for the application titles" ++msgstr "Использовать фиксированную ширину заголовков" ++ ++#: Settings.ui.h:41 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Заголовки приложений имеют одинаковую ширину, даже если они короче " ++"максимальной ширины. Максимальное значение ширины используется как " ++"фиксированная ширина." ++ ++#: Settings.ui.h:42 ++msgid "Display running indicators on unfocused applications" ++msgstr "Индикатор запущенного приложения, когда окно не в фокусе" ++ ++#: Settings.ui.h:43 ++msgid "Use the favorite icons as application launchers" ++msgstr "Показывать избранные приложения" ++ ++#: Settings.ui.h:44 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Скрывать только при наложении окон " ++ ++#: Settings.ui.h:45 ++msgid "The panel hides from" ++msgstr "Скрывать панель с" ++ ++#: Settings.ui.h:46 ++msgid "All windows" ++msgstr "Все окна" ++ ++#: Settings.ui.h:47 ++msgid "Focused windows" ++msgstr "Окна в фокусе" ++ ++#: Settings.ui.h:48 ++msgid "Maximized windows" ++msgstr "Развернутые окна" ++ ++#: Settings.ui.h:49 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Требуется давление на краю экрана, чтобы открыть панель" ++ ++#: Settings.ui.h:50 ++msgid "Required pressure threshold (px)" ++msgstr "Область у границы для показа панели (в пикселях)" ++ ++#: Settings.ui.h:51 ++msgid "Required pressure timeout (ms)" ++msgstr "Задержка показа при приближении к краю (в мс)" ++ ++#: Settings.ui.h:52 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Разрешить отображение панели в полноэкранном режиме" ++ ++#: Settings.ui.h:53 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "" ++"Скрывать дополнительные панели (требуется показ на нескольких мониторах)" ++ ++#: Settings.ui.h:54 ++msgid "e.g. i" ++msgstr "например, i" ++ ++#: Settings.ui.h:55 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Комбинация клавиш для показа панели" ++ ++#: Settings.ui.h:56 ++msgid "Syntax: , , , " ++msgstr "Синтакс: , , , " ++ ++#: Settings.ui.h:57 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Длительность анимации (в мс)" ++ ++#: Settings.ui.h:58 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Задержка перед скрытием панели (в мс)" ++ ++#: Settings.ui.h:59 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Задержка на скрытие при запуске (в мс)" ++ ++#: Settings.ui.h:60 ++msgid "Time (ms) before showing (400 is default)" ++msgstr "Задержка (в мс) перед показом (400 по умолчанию)" ++ ++#: Settings.ui.h:61 ++msgid "Animation time (ms)" ++msgstr "Время анимации (в мс)" ++ ++#: Settings.ui.h:62 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Задержка (в мс) перед скрытием (100 по умолчанию)" ++ ++#: Settings.ui.h:63 ++msgid "Immediate on application icon click" ++msgstr "Сразу по переходу в приложение" ++ ++#: Settings.ui.h:64 ++msgid "Middle click on the preview to close the window" ++msgstr "Нажатие средней кнопкой по предпросмотру закрывает окно" ++ ++#: Settings.ui.h:65 ++msgid "Window previews preferred size (px)" ++msgstr "Предпочитаемый размер окна предпросмотра (пикселей)" ++ ++#: Settings.ui.h:66 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Коэффициент по оси Y (высота)" ++ ++#: Settings.ui.h:67 ++msgid "Window previews padding (px)" ++msgstr "Отступ окон между собой (пикселей)" ++ ++#: Settings.ui.h:68 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:69 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:70 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:71 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:72 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:73 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:74 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:75 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:76 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:77 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:78 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:79 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:80 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:81 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:82 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:83 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:84 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:85 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:86 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:87 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:88 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:89 ++msgid "Fixed" ++msgstr "Закреплено" ++ ++#: Settings.ui.h:90 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Коэффициент по оси Y (ширина)" ++ ++#: Settings.ui.h:91 ++msgid "Use custom opacity for the previews background" ++msgstr "Использовать прозрачность для окна предпросмотра" ++ ++#: Settings.ui.h:92 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "Если отключено используется прозрачность из настроек панели" ++ ++#: Settings.ui.h:93 ++msgid "Close button and header position" ++msgstr "Кнопка закрытия и заголовок" ++ ++#: Settings.ui.h:94 ++msgid "Bottom" ++msgstr "Внизу" ++ ++#: Settings.ui.h:95 ++msgid "Top" ++msgstr "Наверху" ++ ++#: Settings.ui.h:96 ++msgid "Display window preview headers" ++msgstr "Показать заголовок окна" ++ ++#: Settings.ui.h:97 ++msgid "Icon size (px) of the window preview" ++msgstr "Размер значка (в пикселях) в окне предпросмотра" ++ ++#: Settings.ui.h:98 ++msgid "If disabled, the previews icon size will be based on headerbar size" ++msgstr "Если отключено будет использован размер значков по размеру заголовка" ++ ++#: Settings.ui.h:99 ++msgid "Font size (px) of the preview titles" ++msgstr "Размер шрифта (в пикселях) для заголовка" ++ ++#: Settings.ui.h:100 ++msgid "Font weight of the preview titles" ++msgstr "Жирность шрифта заголовка" ++ ++#: Settings.ui.h:101 ++msgid "Font color of the preview titles" ++msgstr "Цвет шрифта заголовка" ++ ++#: Settings.ui.h:102 ++msgid "Enable window peeking" ++msgstr "Переводить окно на передний план" ++ ++#: Settings.ui.h:103 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "Выделение окна приложения при наведении на окно предпросмотра," ++ ++#: Settings.ui.h:104 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Задержка перед помещением окна на передний план (в мс)" ++ ++#: Settings.ui.h:105 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:106 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Время бездействия при наведении указателя на окно предпросмотра для перевода " ++"окна на передний план." ++ ++#: Settings.ui.h:107 ++msgid "Window peeking mode opacity" ++msgstr "Режим прозрачности выделенного окна" ++ ++#: Settings.ui.h:108 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:109 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "Все окна, кроме выделенного, имеют прозрачность." ++ ++#: Settings.ui.h:110 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Задержка между событиями вращения колесика мышки (мс)" ++ ++#: Settings.ui.h:111 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Это значение ограничивает количество получаемых сообщений вращения колесика " ++"мышки." ++ ++#: Settings.ui.h:112 ++msgid "Show popup when changing workspace" ++msgstr "" ++ ++#: Settings.ui.h:113 ++msgid "This affects workspace popup when scrolling on the panel only." ++msgstr "" ++ ++#: Settings.ui.h:114 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:115 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys prefix" ++msgstr "Префикс горячих клавиш" ++ ++#: Settings.ui.h:117 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "" ++"Комбинации клавиш для приложений на панели либо Super+Number, либо Super+Alt" ++"+Num" ++ ++#: Settings.ui.h:118 ++msgid "Never" ++msgstr "Никогда" ++ ++#: Settings.ui.h:119 ++msgid "Show temporarily" ++msgstr "Показать временно" ++ ++#: Settings.ui.h:120 ++msgid "Always visible" ++msgstr "Всегда видимый" ++ ++#: Settings.ui.h:121 ++msgid "Number overlay" ++msgstr "Наложение цифр" ++ ++#: Settings.ui.h:122 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Временно показывать цифры на значках приложений при нажатии горячей клавиши." ++ ++#: Settings.ui.h:123 ++msgid "Hide timeout (ms)" ++msgstr "Задержка скрытия (в мс)" ++ ++#: Settings.ui.h:124 ++msgid "e.g. q" ++msgstr "например, q" ++ ++#: Settings.ui.h:125 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Показать оверлей на значках на 2 секунды" ++ ++#: Settings.ui.h:126 ++msgid "Show window previews on hotkey" ++msgstr "Предпросмотр приложений" ++ ++#: Settings.ui.h:127 ++msgid "Show previews when the application have multiple instances" ++msgstr "Показывать предпросмотр приложений с несколькими экземплярами" ++ ++#: Settings.ui.h:128 ++msgid "Number row" ++msgstr "Основной" ++ ++#: Settings.ui.h:129 ++msgid "Numeric keypad" ++msgstr "Дополнительной" ++ ++#: Settings.ui.h:130 ++msgid "Both" ++msgstr "Оба" ++ ++#: Settings.ui.h:131 ++msgid "Hotkeys are activated with" ++msgstr "Используются горячие клавиши с клавиатуры" ++ ++#: Settings.ui.h:132 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "Выберите какой набор цифровых кнопок используется для горячих клавиш" ++ ++#: Settings.ui.h:133 ++msgid "Current Show Applications icon" ++msgstr "Текущий значок \"Приложения\"" ++ ++#: Settings.ui.h:134 ++msgid "Select a Show Applications image icon" ++msgstr "Выбрать значок \"Приложения\"" ++ ++#: Settings.ui.h:135 ++msgid "Custom Show Applications image icon" ++msgstr "Собственный значок \"Приложения\"" ++ ++#: Settings.ui.h:136 ++msgid "Show Applications icon side padding (px)" ++msgstr "Отступ от значка (в пикселях)" ++ ++#: Settings.ui.h:137 ++msgid "Override escape key and return to desktop" ++msgstr "" ++ ++#: Settings.ui.h:138 ++msgid "Animate Show Applications." ++msgstr "Анимировать Показ списка приложений." ++ ++#: Settings.ui.h:139 ++msgid "Override Show Desktop line color" ++msgstr "Выбрать цвет разделительной линии" ++ ++#: Settings.ui.h:140 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Показать рабочий стол при наведении на кнопку" ++ ++#: Settings.ui.h:141 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Задержка показа рабочего стола (в мс)" ++ ++#: Settings.ui.h:142 ++msgid "Fade duration (ms)" ++msgstr "Задержка скрытия (в мс)" ++ ++#: Settings.ui.h:143 ++msgid "The panel background opacity is affected by" ++msgstr "Влияние на прозрачность панели оказывают" ++ ++#: Settings.ui.h:144 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "" ++"Изменять прозрачность при приближении окна к панели ближе чем (в пикселях)" ++ ++#: Settings.ui.h:146 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Изменять прозрачность на (%)" ++ ++#: Settings.ui.h:147 ++msgid "Opacity change animation duration (ms)" ++msgstr "Скрыть и показать задержка анимации (в мс)" ++ ++#: Settings.ui.h:148 ++msgid "Display the main panel on" ++msgstr "Показать панель на" ++ ++#: Settings.ui.h:149 ++msgid "Display panels on all monitors" ++msgstr "Показать панель на всех мониторах" ++ ++#: Settings.ui.h:150 ++msgid "Panel Intellihide" ++msgstr "Автоскрытие панели" ++ ++#: Settings.ui.h:151 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Скрывать и показывать панель в зависимости от настроек" ++ ++#: Settings.ui.h:152 ++msgid "Order and positions on monitor" ++msgstr "Порядок и расположение на мониторе" ++ ++#: Settings.ui.h:153 ++msgid "Apply changes to all monitors" ++msgstr "Применить изменения ко всем мониторам" ++ ++#: Settings.ui.h:154 ++msgid "Panel screen position" ++msgstr "Расположение панели на экране" ++ ++#: Settings.ui.h:155 ++msgid "Left" ++msgstr "Слева" ++ ++#: Settings.ui.h:156 ++msgid "Right" ++msgstr "Справа" ++ ++#: Settings.ui.h:157 ++msgid "Position" ++msgstr "Расположение" ++ ++#: Settings.ui.h:158 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Ширина панели\n" ++"(По умолчанию 48 пикселей)" ++ ++#: Settings.ui.h:160 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Отступ между значками приложений\n" ++"(по умолчанию 8 пикселей)" ++ ++#: Settings.ui.h:162 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Отступ вокруг значков приложений\n" ++"(по умолчанию 4 пикселя)" ++ ++#: Settings.ui.h:164 ++msgid "Running indicator position" ++msgstr "Позиция индикаторов запущенных приложений" ++ ++#: Settings.ui.h:165 ++msgid "Running indicator style (Focused app)" ++msgstr "Индикатор запущенного приложения (когда в фокусе)" ++ ++#: Settings.ui.h:166 ++msgid "Dots" ++msgstr "Точки" ++ ++#: Settings.ui.h:167 ++msgid "Squares" ++msgstr "Квадраты" ++ ++#: Settings.ui.h:168 ++msgid "Dashes" ++msgstr "Линии" ++ ++#: Settings.ui.h:169 ++msgid "Segmented" ++msgstr "Сегменты" ++ ++#: Settings.ui.h:170 ++msgid "Solid" ++msgstr "Жирные линии" ++ ++#: Settings.ui.h:171 ++msgid "Ciliora" ++msgstr "Линии с точками" ++ ++#: Settings.ui.h:172 ++msgid "Metro" ++msgstr "Метро" ++ ++#: Settings.ui.h:173 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Индикатор запущенного приложения (когда в не фокусе)" ++ ++#: Settings.ui.h:174 ++msgid "Override panel theme background color " ++msgstr "Цвет панели " ++ ++#: Settings.ui.h:175 ++msgid "Override panel theme background opacity" ++msgstr "Прозрачность панели" ++ ++#: Settings.ui.h:177 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Прозрачность панели (%)" ++ ++#: Settings.ui.h:178 ++msgid "Dynamic background opacity" ++msgstr "Динамическая прозрачность" ++ ++#: Settings.ui.h:179 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Изменять прозрачность при приближении окно к панели" ++ ++#: Settings.ui.h:180 ++msgid "Override panel theme gradient " ++msgstr "Градиент панели " ++ ++#: Settings.ui.h:182 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Значение цвета и прозрачности (%) сверху" ++ ++#: Settings.ui.h:184 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Значение цвета и прозрачности (%) снизу" ++ ++#: Settings.ui.h:185 ++msgid "Style" ++msgstr "Вид" ++ ++#: Settings.ui.h:186 ++msgid "Show favorite applications" ++msgstr "Показывать избранные приложения" ++ ++#: Settings.ui.h:187 ++msgid "Show running applications" ++msgstr "Показывать запущенные приложения" ++ ++#: Settings.ui.h:188 ++msgid "Show favorite applications on secondary panels" ++msgstr "Показывать избранные приложения на вторичных панелях" ++ ++#: Settings.ui.h:189 ++msgid "Show AppMenu button" ++msgstr "Показывать кнопку Меню приложения" ++ ++#: Settings.ui.h:190 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Верхняя панель > Показать меню приложения, должно быть включено в Tweak Tool" ++ ++#: Settings.ui.h:191 ++msgid "Show window previews on hover" ++msgstr "Показывать предпросмотр окон при наведении" ++ ++#: Settings.ui.h:192 ++msgid "Show tooltip on hover" ++msgstr "Показывать подсказку при наведении" ++ ++#: Settings.ui.h:193 ++msgid "Isolate Workspaces" ++msgstr "Изолировать рабочие столы" ++ ++#: Settings.ui.h:194 ++msgid "Isolate monitors" ++msgstr "Изолировать мониторы" ++ ++#: Settings.ui.h:195 ++msgid "Click empty space to close overview" ++msgstr "Закрывать обзор при щелчке на свободном месте" ++ ++#: Settings.ui.h:196 ++msgid "Ungroup applications" ++msgstr "Разгруппировать приложения" ++ ++#: Settings.ui.h:197 ++msgid "Behavior" ++msgstr "Поведение" ++ ++#: Settings.ui.h:198 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Поведение при щелчке на значке запущенного приложения." ++ ++#: Settings.ui.h:199 ++msgid "Click action" ++msgstr "Действие при щелчке" ++ ++#: Settings.ui.h:200 ++msgid "Toggle windows" ++msgstr "Показать или свернуть" ++ ++#: Settings.ui.h:201 ++msgid "Scroll panel action" ++msgstr "При прокрутке над панелью" ++ ++#: Settings.ui.h:202 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Поведение при прокрутке колесиком мыши над панелью." ++ ++#: Settings.ui.h:203 ++msgid "Scroll icon action" ++msgstr "При прокрутке над значком приложения" ++ ++#: Settings.ui.h:204 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Поведение при прокрутке колесиком мыши над значком приложения." ++ ++#: Settings.ui.h:205 ++msgid "Do nothing" ++msgstr "Ничего не делать" ++ ++#: Settings.ui.h:206 ++msgid "Switch workspace" ++msgstr "Переключать рабочий стол" ++ ++#: Settings.ui.h:207 ++msgid "Cycle windows" ++msgstr "Переключать окна" ++ ++#: Settings.ui.h:208 ++msgid "Change volume" ++msgstr "Изменить громкость" ++ ++#: Settings.ui.h:209 ++msgid "Same as panel" ++msgstr "Как на панеле" ++ ++#: Settings.ui.h:210 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Использовать Super+(0-9) как горячие клавиши запуска приложений. Доступно " ++"использование Shift и Ctrl." ++ ++#: Settings.ui.h:211 ++msgid "Use hotkeys to activate apps" ++msgstr "Использовать горячие клавиши для запуска приложений" ++ ++#: Settings.ui.h:212 ++msgid "Action" ++msgstr "Действия" ++ ++#: Settings.ui.h:213 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Размер шрифта в трее\n" ++"(0 = значение из темы)" ++ ++#: Settings.ui.h:215 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Размер шрифта левой панели\n" ++"(0 = значение из темы)" ++ ++#: Settings.ui.h:217 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Отступ между значками в трее\n" ++"(-1 = значение из темы)" ++ ++#: Settings.ui.h:219 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Значки статуса\n" ++"(-1 = значение из темы)" ++ ++#: Settings.ui.h:221 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Отступ левой панели\n" ++"(0 = значение из темы)" ++ ++#: Settings.ui.h:223 ++msgid "Animate switching applications" ++msgstr "Анимировать переключение приложений" ++ ++#: Settings.ui.h:224 ++msgid "Animate launching new windows" ++msgstr "Анимировать запуск нового окна" ++ ++#: Settings.ui.h:225 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Сохранить панель GNOME при показе приложений" ++ ++#: Settings.ui.h:226 ++msgid "Force Activities hot corner on primary monitor" ++msgstr "" ++ ++#: Settings.ui.h:227 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "" ++"Активировать кнопки на панели меню (например, меню даты) только при нажатии " ++"на кнопку" ++ ++#: Settings.ui.h:228 ++msgid "Keep original gnome-shell top panel" ++msgstr "Сохранить верхнюю панель GNOME" ++ ++#: Settings.ui.h:229 ++msgid "App icon secondary (right-click) menu" ++msgstr "Меню приложения по щелчку правой кнопкой мыши" ++ ++#: Settings.ui.h:231 ++msgid "Fine-Tune" ++msgstr "Тонкая настройка" ++ ++#: Settings.ui.h:232 ++msgid "version: " ++msgstr "версия: " ++ ++#: Settings.ui.h:233 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:234 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Кнопками ниже можно сохранить текущие настройки в файл для загрузки на " ++"другой машине." ++ ++#: Settings.ui.h:235 ++msgid "Export and import settings" ++msgstr "Сохранение и загрузка настроек" ++ ++#: Settings.ui.h:236 ++msgid "Export to file" ++msgstr "Сохранение настроек" ++ ++#: Settings.ui.h:237 ++msgid "Import from file" ++msgstr "Загрузка настроек" ++ ++#: Settings.ui.h:238 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "Позволяет обновлять приложение прямо с GitHub." ++ ++#: Settings.ui.h:239 ++msgid "Updates" ++msgstr "Обновления" ++ ++#: Settings.ui.h:240 ++msgid "Periodically check for updates" ++msgstr "Периодически проверять обновления" ++ ++#: Settings.ui.h:241 ++msgid "Check now" ++msgstr "Проверить сейчас" ++ ++#: Settings.ui.h:242 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Внимание! Хоть релизы и выходят " ++"официально, они могут быть еще выложены на extensions.gnome.org! Прочитать" ++ ++#: Settings.ui.h:243 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Эта программа поставляется без каких-либо гарантий.\n" ++"Подробнее на GNU General Public License, version 2 or later" ++ ++#: Settings.ui.h:245 ++msgid "About" ++msgstr "О приложении" ++ + #~ msgid "CPU" + #~ msgstr "ЦП" + +@@ -527,3 +1787,132 @@ msgstr "Показывать значок корзины на рабочем с + + #~ msgid "Window management and application launching" + #~ msgstr "Управление окнами и запуск приложений" ++ ++#~ msgid "Top, with plugin icons collapsed to bottom" ++#~ msgstr "Сверху, иконки плагинов снизу" ++ ++#~ msgid "Left, with plugin icons collapsed to right" ++#~ msgstr "Слева, иконки плагинов справа" ++ ++#~ msgid "Top, with fixed center plugin icons" ++#~ msgstr "Сверху, иконки плагинов по середине" ++ ++#~ msgid "Left, with fixed center plugin icons" ++#~ msgstr "Слева, иконки плагинов по середине" ++ ++#~ msgid "Top, with floating center plugin icons" ++#~ msgstr "Сверху, иконки плагинов по центру и не закреплены" ++ ++#~ msgid "Left, with floating center plugin icons" ++#~ msgstr "Слева, иконки плагинов по центру и не закреплены" ++ ++#~ msgid "Center, fixed in middle of monitor" ++#~ msgstr "По центру монитора" ++ ++#~ msgid "Center, floating between top and bottom elements" ++#~ msgstr "По центру между элементами сверху и снизу" ++ ++#~ msgid "Center, floating between left and right elements" ++#~ msgstr "По центру между элементами слева и справа" ++ ++#~ msgid "Top of plugin icons" ++#~ msgstr "Сверху от иконок плагинов" ++ ++#~ msgid "Left of plugin icons" ++#~ msgstr "Слева от иконок плагинов" ++ ++#~ msgid "Bottom of plugin icons" ++#~ msgstr "Снизу от иконок плагинов" ++ ++#~ msgid "Right of plugin icons" ++#~ msgstr "Справа от иконок плагинов" ++ ++#~ msgid "Top of system indicators" ++#~ msgstr "Сверху от системных индикаторов" ++ ++#~ msgid "Left of system indicators" ++#~ msgstr "Слева от системных индикаторов" ++ ++#~ msgid "Bottom of system indicators" ++#~ msgstr "Снизу от системных индикаторов" ++ ++#~ msgid "Right of system indicators" ++#~ msgstr "Справа от системных индикаторов" ++ ++#~ msgid "Left of taskbar" ++#~ msgstr "Слева от списка задач" ++ ++#~ msgid "Bottom of taskbar" ++#~ msgstr "Снизу от списка задач" ++ ++#~ msgid "Right of taskbar" ++#~ msgstr "Справа от списка задач" ++ ++#~ msgid "Multi-monitors options" ++#~ msgstr "Настройки для нескольких мониторов" ++ ++#~ msgid "Event logs" ++#~ msgstr "Просмотр логов" ++ ++#~ msgid "System" ++#~ msgstr "Система" ++ ++#~ msgid "Device Management" ++#~ msgstr "Управление устройствами" ++ ++#~ msgid "Disk Management" ++#~ msgstr "Управление дисками" ++ ++#~ msgid "Terminal" ++#~ msgstr "Терминал" ++ ++#~ msgid "Files" ++#~ msgstr "Файлы" ++ ++#~ msgid "Display favorite applications on all monitors" ++#~ msgstr "Показывать закрепленные приложения на всех мониторах" ++ ++#~ msgid "Display the clock on all monitors" ++#~ msgstr "Показывать часы на всех мониторах" ++ ++#~ msgid "Display the status menu on all monitors" ++#~ msgstr "Показывать системные индикаторы на всех мониторах" ++ ++#~ msgid "Taskbar position" ++#~ msgstr "Позиция панели задач на экране" ++ ++#~ msgid "Clock location" ++#~ msgstr "Позиция часов" ++ ++#~ msgid "Show Applications icon" ++#~ msgstr "Показывать иконку Программы" ++ ++#~ msgid "Raise window" ++#~ msgstr "Восстановить окно" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Цвет подсветки" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Задержка превью в (мс)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Если установлено слишком маленькое значение, превью может исчезать " ++#~ "слишком быстро. Если установлено слишком большое значение, превью может " ++#~ "долго не скрываться и перекрывать соседние области." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Средний клик закрывает окно" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Ширина окна в предпросмотре (в пикселях)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Высота окна в предпросмотре (в пикселях)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Отступ между окнами в предпросмотре (в пикселях)" +diff --git a/po/sv.po b/po/sv.po +index 33eba9f4..ad8f0009 100644 +--- a/po/sv.po ++++ b/po/sv.po +@@ -469,7 +469,7 @@ msgstr "Ändra bakgrund…" + msgid "Display Settings" + msgstr "Visningsinställningar" + +-#: desktopGrid.js:335 ++#: desktopGrid.js:335 appIcons.js:1726 + msgid "Settings" + msgstr "Inställningar" + +@@ -556,6 +556,1224 @@ msgstr "Visa papperskorgsikon" + msgid "Show the trash icon in the desktop." + msgstr "Visa papperskorgsikonen på skrivbordet." + ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Topp, med tilläggsikoner kollapsade till botten" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Vänster, med tilläggsikoner kollapsade till höger" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Topp, med centrerade tilläggsikoner" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Vänster, med centrerade tilläggsikoner" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Topp, med flytande centrerade tilläggsikoner" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Vänster, med flytande centrerade tilläggsikoner" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Centrum, fixerade i mitten av skärmen" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Centrum, flytande mellan topp och botten elementer" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Centrum, flytande mellan vänster och höger elementer" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Ovanför tilläggsikoner" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "Till vänster av tilläggsikoner" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Under tilläggsikoner" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "Till höger om tilläggsikoner" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Ovanför systemindikatorer" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "Till vänster om systemindikatorer" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Under systemindikatorer" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "Till höger om systemindikatorer" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Ovanför programfältet" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "Till vänster om programfältet" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Under programfältet" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "Till höger om programfältet" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Visa skrivbordsknapp höjd (px)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Visa skrivbordsknapp bredd (px)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Inställningar för programsymboler" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "Återställ till grundinställningar" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Förvalda (primära skärmar)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Bildskärm " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Inställningar för flera bildskärmar" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Inställningar för dynamisk genomskinlighet" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Inställningar för automatisk döljande" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Inställningar för Program-meny" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Inställningar för skrivbordsknappen" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "Förhandsgranskning av programfönster inställningar" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "Inställningar för icke grupperade program" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "Anpassa mittenklick beteendet" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "Anpassa beteendet för panelbläddrande" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "Anpassa beteendet för bläddrande av ikoner" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "Avancerade inställningar för snabbtangenter" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "Sekundära meny inställningar" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "Avancerade inställningar" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "Exportera inställningar" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "Importera inställningar" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "Visa detaljer" ++ ++#: appIcons.js:1398 ++msgid "New Window" ++msgstr "Ny fönster" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Avsluta" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "Fönster" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "Energi inställningar" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "Händelseloggar" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "System" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "Administrering av enheter" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "Administrering av diskar" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "Terminal" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "Systemövervakning" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "Filer" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "Lås upp aktivitetsfältet" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "Lås aktivitetsfältet" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "Dash to Panel inställningar" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "Återställ fönster" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "Visa skrivbordet" ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Ännu ingenting!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"När inställt på att minimera, dubbelklickande minimerar alla fönster av " ++"programm." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Shift+klicka åtgärd" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Höja fönster" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Minimera fönster" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Starta en till förekomst av programmet" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Bläddra bland fönster" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Bläddra fönster + minimera" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Växla enskilda / Förhandsvisa flera" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Beteende för mittenklick." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Mittenklick åtgärd" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Beteende för Shift+mittenklick." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Shift+mittenklick åtgärd" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Isolera bildskärmar" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Visa favoritprogram på alla bildskärmar" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Visa klockan på alla bildskärmar" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Visa statusmeny på alla bildskärmar" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Integrera programmeny objekt" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Visa detaljer menyförval" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Belys fokuserade program" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Dominanta ikonfärgen" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Anpassad färg" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Belysningens genomskinlighet" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "Indikatorhöjd (px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Indikatorfärg - dominant ikon" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Indikatorfärg - åsidosatt tema" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 fönster öppnad (eller inte grupperad)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Tillämpa för alla" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 fönster öppna" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 fönster öppna" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4+ fönster öppna" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Använd olika för icke fokuserade" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Typsnitt storlek (px) på programtitlar (förinställd på 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Typsnitt tjocklek av programtitlar" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "ärver från tema" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normal" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "tunnare" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "tjock" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "tjockare" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Typsnitt färg av programtitlar" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Maximal bredd (px) av programtitlar (förinställning är 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Använd fast bredd för programtitlar" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Programtitlar har samma bredd även om texten är kortare än den maximala " ++"bredden. Den maximala vidden används som mått på fast bredd." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Visa körande indikatorer på ofokuserade program" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Använd favoritikoner som programstartare" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Endast dölj panelen om den täcks av fönster " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "Panelen döljs från" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Alla fönster" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Fokuserade fönster" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Maximerade fönster" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Kräv tryck vid kanten på skärmen för att visa panelen" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Tröskelvärde som krävs för trycket (px)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Tidsgräns som krävs för trycket (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Tillåt panelen att synas i fullskärmsläge" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "" ++"Göm endast sekundära paneler (kräver inställningar för flera bildskärmar)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "t ex i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Snabbkommando för att syna och hålla panelen" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Syntax: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Tidsgräns för göm och syna animeringen (ms)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Fördröjning innan panelen göms (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Fördröjning innan automatisk döljande aktiveras vid starten (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Tiden (ms) innan visning (förinställd på 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Animationstid (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Tiden (ms) innan gömmande (förinställd på 100)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Genast vid klickande på programikonen" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Mittenklicka för att förhandsvisning för att stänga fönster" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Föredra fönsterstorlek på förhandsvisning (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Fönster förhandsvisningens bildförhållande Y (höjd)" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Fönster förhandsvisningens utfyllnad (px)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Fast" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Fönster förhandsvisningens bildförhållande X (bredd)" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Använd anpassad genomskinlighet för förhandsvisningens bakgrund" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Om avaktiverad, förhandsvisningen kommer att ha samma genomskinlighet som " ++"panelen" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Stäng knappen och titelposition" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Under" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Topp" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Visa rubrik i fönster förhandsvisningen" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Typsnitt storlek (px) på förhandsvisningens titlar" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Typsnitt tjocklek på förhandsvisningens titlar" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Typsnitt färg på förhandsvisningens titlar" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Aktivera fönstermarkering" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"När en muspekare svävar över förhandsvisning av fönster under en tid, då " ++"kommer fönstret att framträda." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Startar fönstermarkerande läge tidsgräns (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Tid av inaktivitet då muspekare svävar på fönster förhandsvisning som behövs " ++"till att aktivera fönstermarkerande läge." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Fönstermarkerande läge genomskinlighet" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "Alla fönster förutom de markerade har samma genomskinlighet." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Fördröjning mellan bläddrande händelser med mushjulet (ms)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Använd detta värde för att begränsa numret av uppfångade bläddrande med " ++"mushjulet." ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Snabbkommando prefix" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "" ++"Snabbkommando kommer att antingen vara Super+Nummer eller Super+Alt+Num" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Alldrig" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Visa tillfälligt" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Alltid synlig" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Nummer av övertäckande" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "Tillfälligt visa programnummer över ikoner när snabbkommando används." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Tidsgränsen för döljandet (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "t ex q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Snabbkommando för att visa övertäckande i 2 sekunder" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Visa fönsterförhandsvisningar baserad på snabbkommando" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Presentera förhandsvisningar när programmet har flera förekomster" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Raden med nummerknappar" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Numeriskt knappsats" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "Båda" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Snabbkommando aktiveras med" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Välj vilka tangentbordsknappar ska användas för att aktivera snabbkommando" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Nuvarande Visa Program ikonen" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Välj en bild för Visa Program ikonen" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Anpassad bild för Visa Program ikonen" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Visa Program ikonens utfyllnad (px)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Visa skrivbord när muspekaren svävar över skrivbordsknappen" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Fördröjningen innan skrivbord visas (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Varaktighet på bleknande (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "Genomskinligheten på panelens bakgrund påverkas av" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Ändra genomskinlighet när fönster blir närmare än (px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Ändra genomskinlighet till (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Ändringstiden för genomskinlighet animationen (ms)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Panelpositionen på skärmen" ++ ++#: Settings.ui.h:145 ++msgid "Left" ++msgstr "Vänster" ++ ++#: Settings.ui.h:146 ++msgid "Right" ++msgstr "Höger" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Aktivitetsfältets position" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Placering av klockan" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Visa huvudpanelen på" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Visa paneler på alla bildskärmar" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Automatisk gömmande av panelen" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Göm och visa panelen beroende på inställningar" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Position" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Panelstorlek\n" ++"(48 är standard)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Programikonernas marginaler\n" ++"(8 är standard)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Programikonernas avståndsutfyllnad\n" ++"(grundläge är 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Aktiv indikeringsposition" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Stilen för aktiv indikering (fokuserad program)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Punkter" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Kvadrater" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Sträck" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Segmenterade" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Fasta" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Stilen för aktiv indikering (icke fokuserade program)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Åsidosätt paneltemans bakgrundsfärg " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Åsidosätt paneltemans genomskinlighet av bakgrund" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Panelens genomskinlighet av bakgrund (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Dynamisk genomskinlighet av bakgrund" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Ändra genomskinlighet av bakgrund när en fönster kommer nära panelen" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Åsidosätt paneltemans gradient " ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Toppgradientens färg och genomskinlighet (%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Bottengradientens färg och genomskinlighet (%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Stil" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Visa favoritprogram" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Visa program som körs" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Visa Program ikonen" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Animera Visa Program." ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Visa Aktiviteter knappen" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Visa Skrivbord knappen" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Visa Program Meny knappen" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Övre Fältet > Visa Program Meny måste aktiveras i Justeringar (Tweak Tool)" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Visa förhandsgranskning av fönster vid svävande av muspekaren" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Visa beskrivning vid svävande av muspekaren" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Isolera Arbetsytor" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Avgruppera program" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Beteende" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Beteende när ikonen med redan körande program klickas på." ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Klickande" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Växla fönster" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Åtgärd för skrollande av panelen" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Beteende då mushjulet bläddras över panelen." ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Skrollande ikonens åtgärd" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Beteende då mushjulet skrollar över en programikon." ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Gör ingenting" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Ändra arbetsyta" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Växla bland fönster" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Aktivera Super+(0-9) som snabba genvägar för att aktivera program. Det kan " ++"också användas tillsammans med Shift och Ctrl." ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "Använd snabbkommando för att aktivera program" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "Åtgärd" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Teckenstorlek för meddelandefältet\n" ++"(0 = temans standard)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Typsnitt storlek på vänster sida\n" ++"(0 = temans standard)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Utfyllnadsavstånd för meddelandefältets objekt\n" ++"(-1 = temans standard)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Utfyllnadsavstånd för statusikon\n" ++"(-1 = temans standard)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Utfyllnadsavstånd på vänstersida\n" ++"(-1 = temans standard)" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "Animera programbyte" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "Animera uppstart av nya fönster" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Behåll den ursprungliga GNOME-skalets översikt" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "Aktivera panelens menyknappar (t ex datum meny) endast vid klickandet" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "Programikonens sekundära (högerklick) meny" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "Finjustera" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "version: " ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Använd knapparna nedan för att skapa en inställningsfil för de gällande " ++"förval som sedan kan importeras vid en annan installation." ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "Exportera och importera inställningar" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "Exportera till en fil" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "Importera från en fil" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "" ++"Detta gör det möjligt för dig att uppdatera tillägget direkt från GitHub " ++"förrådet." ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "Uppdateringar" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "Regelmässigt kolla efter uppdateringar" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "Kolla nu" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Var medveten om att dessa officiella " ++"Dash to Panel utgåvor kan ännu vara icke recenserade på extensions.gnome.org!" ++" Läs mer" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Detta program kommer ABSOLUT UTAN NÅGON GARANTI.\n" ++"Se GNU " ++"General Public Licens, version 2 eller senare för detaljer." ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "Information om programmet" ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -564,3 +1782,52 @@ msgstr "Visa papperskorgsikonen på skrivbordet." + + #~ msgid "Huge" + #~ msgstr "Enorm" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Markeringsfärg" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Fördröjning i förhandsgranskning av döljande ikonen (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Om den är satt för lågt, kommer fönsterförhandvisning av körande program " ++#~ "se ut att att stängas för snabbt när det återgår. Om satt för högt så " ++#~ "kommer fönsterförhandvisning att hänga kvar för länge när det flyttas " ++#~ "till närliggande ikonen." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Mittenklick för att stänga fönster" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Bredden på förhandsvisningar av fönster (px)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Höjden på förhandsvisningar av fönster (px)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Avstånd mellan förhandsvisningar av fönster (px)" ++ ++#~ msgid "Natural" ++#~ msgstr "Naturell" ++ ++#~ msgid "Left side of panel" ++#~ msgstr "Vänster sida av panelen" ++ ++#~ msgid "Centered in content" ++#~ msgstr "Centrerad i innehållet" ++ ++#~ msgid "Github" ++#~ msgstr "Github" ++ ++#~ msgid "Height (px)" ++#~ msgstr "Höjd (px)" ++ ++#~ msgid "Color - Override Theme" ++#~ msgstr "Färg - Åsidosatt Tema" ++ ++#~ msgid "1 window open" ++#~ msgstr "1 Fönster öppnad" +diff --git a/po/tr.po b/po/tr.po +index 30ceafa0..7fe0943b 100644 +--- a/po/tr.po ++++ b/po/tr.po +@@ -476,7 +476,7 @@ msgstr "Arka Planı Değiştir…" + msgid "Display Settings" + msgstr "Görüntü Ayarları" + +-#: desktopGrid.js:332 ++#: desktopGrid.js:332 appIcons.js:1726 + msgid "Settings" + msgstr "Ayarlar" + +@@ -556,8 +556,1295 @@ msgstr "Çöp kutusunu göster" + msgid "Show the trash icon in the desktop." + msgstr "Çöp kutusu simgesini masaüstünde göster." + ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "Üst, eklenti simgeleri alta kaydırılır" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "Sol, eklenti simgeleri sağa kaydırılır" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "Üst, eklenti simgeleri ortada sabit kalır" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "Sol, eklenti simgeleri ortada sabit kalır" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "Üst, eklenti simgeleri ortada değişken" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "Sol, eklenti simgeleri ortada değişken" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "Merkez, ekranın ortasında sabit kalır" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "Merkez, üst ve alt elemanlar arasında değişken" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "Merkez, sol ve sağ değişken" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "Eklenti simgelerinin üstünde" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "Eklenti simgelerinin solunda" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "Eklenti simgelerinin altında" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "Eklenti simgelerinin sağında" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "Sistem tepsisinin üstünde" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "Sistem tepsisinin solunda" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "Sistem tepsisinin altında" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "Sistem tepsisinin sağında" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "Görev çubuğunun üstünde" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "Görev çubuğunun solunda" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "Görev çubuğunun altında" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "Görev çubuğunun sağında" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "Masaüstü Göster düğmesi yüksekliği (piksel)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "Düğme genişliği (piksel)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "Çalışan Gösterge Seçenekleri" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "Varsayılanlara Dön" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "Varsayılan (Birincil ekran)" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "Ekran " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "Çoklu Ekran Seçenekleri" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "Dinamik Saydamlık Seçenekleri" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "Otomatik gizleme seçenekleri" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "Tüm Uygulamalar Seçenekleri" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "Masaüstü Göster Seçenekleri" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "Pencere Önizleme Seçenekleri" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "Gruplanmamış Uygulama Seçenekleri" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "Orta Tıklatma Davranışları" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "Panel kaydırma davranışını özelleştir" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "Simge kaydırma davranışını özelleştir" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "Gelişmiş kısayol tuş seçenekleri" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "İkincil Menü Seçenekleri" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "Gelişmiş Seçenekler" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "Dışarı aktarma ayarları" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "İçeri aktarma ayarları" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "Ayrıntıları Göster" ++ ++#: appIcons.js:1398 ++msgid "New Window" ++msgstr "Yeni Pencere" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "Çık" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "Pencere" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "Güç seçenekleri" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "Olay günlükleri" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "Sistem" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "Aygıt Yönetimi" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "Disk Yönetimi" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "Uçbirim" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "Sistem monitörü" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "Dosyalar" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "Görev Çubuğu Kilidini Aç" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "Görev Çubuğunu Kilitle" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "Dash to Panel Ayarları" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "Pencereleri Onar" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "Masaüstünü Göster" ++ ++#: update.js:58 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "Sürüm %s (%s) kullanılabilir" ++ ++#: update.js:59 ++msgid "Details" ++msgstr "Ayrıntılar" ++ ++#: update.js:60 ++msgid "Update" ++msgstr "Güncelle" ++ ++#: update.js:63 ++msgid "Already up to date" ++msgstr "Zaten güncel" ++ ++#: update.js:148 ++msgid "Update successful, please log out/in" ++msgstr "Güncelleme başarılı, lütfen çıkış yapın/girin" ++ ++#: update.js:149 ++msgid "Log out" ++msgstr "Çıkış yap" ++ ++#: update.js:153 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "Güncelleme başarılı, lütfen Gnome Kabuğunu yeniden başlat" ++ ++#: update.js:154 ++msgid "Restart GNOME Shell" ++msgstr "Gnome Kabuğunu yeniden başlat" ++ ++#: update.js:154 ++msgid "Restarting GNOME Shell..." ++msgstr "Gnome Kabuğunu yeniden başlatılıyor..." ++ ++#: update.js:160 ++msgid "Error: " ++msgstr "Hata: " ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "Henüz bir şey yok!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"Küçültmek için ayarlandığında, çift tıklayarak tüm uygulama pencerelerini " ++"küçültür." ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Shift+Tıklama eylemi" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "Pencereleri yükselt" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "Pencereyi küçült" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "Yeni uygulama başlat" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "Pencereler döngüsü" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "Uygulama başlat ve küçült" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "Tek geçiş/çoklu önizleme" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "Orta tıklama davranışı." ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "Orta tıklama eylemi" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Shift + Orta tıklama davranışı." ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Shift+Orta Tıklama eylemi" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "Ekranları izole et" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "Tüm ekranlarda sık kullanılan uygulamaları göster" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "Tüm ekranlarda saati göster" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "Tüm ekranlarda durum menüsünü göster" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "Entegre Program menüsü" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "Ayrıntıları Göster menü seçeneği" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "Vurgu odaklı uygulamalar" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "Simge baskın renk" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "Özel renk" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "Arka ışık saydamlığı" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "Yükseklik (piksel)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "Gösterge rengi - baskın simge" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "Gösterge rengi - temayı geçersiz kıl" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "Bir pencere açık olduğunda (gruplandırılmadığında)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "Tümüne uygula" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "İki pencere açık olduğunda" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "Üç pencere açık olduğunda" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "Dört + pencere açık olduğunda" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "Odakta değilken diğerini kullan" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "Uygulama başlığı yazı tipi boyutu (piksel) (varsayılan 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "Uygulama başlığı yazı tipi" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "mevcut tema" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normal" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "hafif" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "kalın" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "çok kalın" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "Uygulama başlığı yazı tipi rengi" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "Uygulama başlığı azami genişliği (piksel) (varsayılan 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "Sabit başlık genişliğini kullan" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"Uygulama başlıkları, metinleri azami genişlikten daha kısa olsa bile, aynı " ++"genişliğe sahiptir. Azami genişlik değeri sabit genişlik olarak kullanılır." ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "Odaklanmamış uygulamalarda çalışan göstergeleri görüntüle" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "Sık kullanılanlar simgelerini başlatıcı olarak kullanma" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "Sadece pencere tarafından engellendiğinde paneli gizle " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "Panel gizlenir" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "Tüm pencereler" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "Odaklanmış pencereler" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "Büyütülmüş pencereler" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "Paneli ortaya çıkarmak için ekranın kenarında beklemek gerektirir" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "Başlatma için gereken alan eşiği (piksel)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "Bekleme için gerekli zaman aşımı (ms)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "Panelin tam ekran kipinde ortaya çıkmasına izin ver" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "Yalnızca ikincil panelleri gizle (çoklu monitör seçeneği gerekir)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "örneğin. i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "Paneli tutmak ve ortaya çıkarmak için klavye kısayolu" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "Sözdizimi: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "Canlandırma süresini gizle ve göster (ms)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "Paneli gizlemeden önce gecikme süresi (ms)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "Başlangıçta intellihide'ı etkinleştirmeden önce gecikme (ms)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Göstermeden önce geçen süre (ms) (varsayılan 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "Animasyon süresi (ms)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "Gizlemeden önce geçen süre (ms) (varsayılan 100)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "Hemen uygulama simgesine tıkla" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "Pencereyi kapatmak için önizlemeye orta tıkla" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "Pencere önizlemeleri tercih edilen boyut (px)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "Pencere önizlemeleri en boy oranı Y (yükseklik)" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "Pencere önizlemeleri dolgu (px)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "Sabit" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "Pencere önizlemeleri en boy oranı X (genişlik)" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "Önizleme arka planı için özel opaklık kullan" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "" ++"Devre dışı bırakılırsa, önizleme arka planı panelin aynı opaklığına sahip " ++"olur" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "Kapat düğmesi ve üstbilgi konumu" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "Alt" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "Üst" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "Pencere önizleme başlıklarını görüntüle" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "Önizleme başlıklarının yazı tipi boyutu (px)" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "Önizleme başlıklarının yazı tipi genişliği" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "Önizleme başlıklarının yazı tipi rengi" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "Pencereye göz atmayı etkinleştir" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "" ++"Bir süre boyunca bir pencere önizlemesinin üzerine gelindiğinde, pencere " ++"ayırt edilir." ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "Pencere gözatma kipi zaman aşımı (ms)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "" ++"Bir pencere önizleme üzerinde vurgulama sırasında etkinlik dışı zaman girmek " ++"için gerekli pencere göz atma kipi." ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "Pencere gözatma kipi saydamlığı" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "" ++"Bakılan pencerenin dışındaki tüm pencerelerin opaklıkları aynı değere " ++"ayarlanmıştır." ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "Fare kaydırma olayları arasındaki gecikme (ms)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "" ++"Yakalanan fare kaydırma olaylarının sayısını sınırlamak için bu değeri " ++"kullanın." ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "Kısayol tuşları" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Kısayol Super+Numaralar, yada Super+Alt" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "Asla" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "Geçici olarak göster" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "Sürekli görünür" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "Numara yerleşimi" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Kısayol tuşlarını kullanırken uygulama numaralarını simgeler üzerinde geçici " ++"olarak göster." ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "Gizleme sonlanma (ms)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "örneğin. q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "2 saniye kaplama göstermek için kısayol" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "Uygulama önizleme kısayol" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "Uygulamanın birden çok örneği açık olduğunda önizlemeleri göster" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "Numara satırı" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "Sayısal tuş takımı" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "İkiside" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "Kısayol tuşları ile etkin" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "" ++"Kısayol tuşlarını etkinleştirmek için hangi klavye sayı tuşlarının " ++"kullanılacağını seçin" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "Mevcut simgeyi göster" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "Görünmesini istediğin simgeyi seç" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "Görünmesini istediğin simgeyi seç" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "Simge yan dolgu (piksel)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "Masaüstünü göster düğmesinin üstüne gelince masaüstü görünsün" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "Masaüstünü ortaya çıkarmadan önce gecikme (ms)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "Solma süresi (ms)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "Panelin saydamlık üzerindeki etkisi" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "Bir pencere yaklaştığında saydamlığı değiştir (piksel)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "Saydamlığı değiştir (%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "Saydamlık değişimi canlandırma süresi (ms)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "Panelin Ekrandaki Konumu" ++ ++#: Settings.ui.h:145 ++msgid "Left" ++msgstr "Sol" ++ ++#: Settings.ui.h:146 ++msgid "Right" ++msgstr "Sağ" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "Görev çubuğu konumu" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "Saat konumu" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "Paneli ana ekranda göster" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "Paneli tüm ekranlarda göster" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "Paneli gizle" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "Paneli gizleme ve geri getirme seçenekleri" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "Konum" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Panel Boyutu\n" ++"(varsayılan 48)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Uygulama Simge Marjı\n" ++"(varsayılan 8)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"Uygulama Simge Dolgusu\n" ++"(varsayılan 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "Çalışan uygulamaların gösterge konumu" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "Çalışan uygulamaların gösterge biçimi (Odakta olan)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "Noktalar" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "Kareler" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "Tireler" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "Segmentler" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "Kalın çizgi" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Nokta ve çizgi" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Çalışan uygulamaların gösterge biçimi (Odakta olmayan)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "Panel tema arka plan rengini geçersiz kıl " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "Panel tema arka plan saydamlığını geçersiz kıl" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "Panel arka plan saydamlığı (%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "Dinamik arka plan saydamlığı" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "Bir pencere panele yaklaştığında saydamlığı değişir" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "Panel temasında değişken renkler kullan " ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "Değişken renk ve saydamlık değeri (%) üst" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "Değişken renk ve saydamlık değeri (%) alt" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "Biçim" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "Sık kullanılan uygulamaları göster" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "Çalışan uygulamaları göster" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "Tüm Uygulamalar simgesi Aktif" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "Canlandırma menü açılışlarında göster." ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "Etkinlikler düğmesi Aktif" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "Masaüstünü göster düğmesi Aktif" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "Uygulama menüleri düğmesi Aktif" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "Gnome İnce Ayarlar/Tepe Çubuğu/Uygulama Menüsü etkin olmalıdır" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "Pencere önizlemelerini göster" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "Vurgulu araç ipucunu göster" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "Çalışma alanlarını ayır" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "Gruplandırılmamış uygulamalar" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "Davranış" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Çalışan bir uygulamanın simgesine tıkladığınızda davranış." ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "Tıklama eylemi" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "Pencereleri aç/kapat" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "Kaydırma paneli eylemi" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "Panel üzerinde fare kaydırırken davranış." ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "Kaydırma simgesi eylemi" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "Bir uygulama simgesi üzerinde fareyi kaydırırken davranış." ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "Hiçbir şey yapma" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "Çalışma alanını değiştir" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "Pencere döngüsü" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Uygulamaları etkinleştirmek için kısayollar ctrl +(0-9) etkinleştirin Shift " ++"ve Ctrl ile birlikte." ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "Uygulamaları etkinleştirmek için kısayol tuşlarını kullan" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "Eylem" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Simge Font Boyutu\n" ++"(0 = varsayılan)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"SolKutu Yazı Boyutu\n" ++"(0 = varsayılan)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Simge Dolgusu\n" ++"(-1 = varsayılan)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Durum Simge Dolgusu\n" ++"(-1 = varsayılan)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"SolKutu Dolgusu\n" ++"(-1 = varsayılan)" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "Uygulama geçişlerinde canlandırma kullan" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "Açılan pencerelerde canlandırma kullan" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "Orijinal gnome-shell rıhtımını kullan (genel bakış)" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "" ++"Sadece tıklandığında panel menü düğmelerini (ör. tarih menüsü) etkinleştir" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "Uygulama simgesi ikincil (sağ tık) menüsü" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "İnce Ayarlar" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "sürüm: " ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"Geçerli ayarlarınızı yedeklemek için aşağıdaki düğmeleri kullanın farklı bir " ++"makinede içe aktarılabilen tercihler." ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "Ayarları içeri ve dışarı aktar" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "Dışarı aktar" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "İçeri aktar" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "Bu, eklentiyi GitHub deposundan doğrudan güncellemenizi sağlar." ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "Güncellemeler" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "Güncellemeleri düzenli olarak kontrol et" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "Şimdi kontrol et" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"Unutmayın, Dash to Panel bültenleri " ++"extensions.gnome.org üstünde henüz hazır olmayabilir! Devamını oku" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Bu program KESİNLİKLE HİÇBİR GARANTİ vermez.\n" ++"Bakın GNU " ++"Genel Kamu Lisansı, sürüm 2 veya üstü detaylar için." ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "Hakkında" ++ + #~ msgid "CPU" + #~ msgstr "İşlemci" + + #~ msgid "Memory" + #~ msgstr "Bellek" ++ ++#~ msgid "Highlight color" ++#~ msgstr "Arka ışık rengi" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "Önizleme zaman aşımı simgesi (ms)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "Çok düşük ayarlanırsa, çalışan uygulamaların pencere önizlemesi kapanıyor " ++#~ "gibi görünebilir hızlı açılır pencere. Çok yüksek ayarlarsanız, önizleme " ++#~ "olabilir bitişik bir simgeye taşınırken çok uzun süre bekler." ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "Pencereyi kapatmak için orta tık" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "Pencere önizleme genişliği (piksel)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "Pencere önizleme yüksekliği (piksel)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "Pencere önizleme dolgusu (piksel)" +diff --git a/po/uk.po b/po/uk.po +index 8ea5aaf9..4ec6e534 100644 +--- a/po/uk.po ++++ b/po/uk.po +@@ -335,6 +335,443 @@ msgstr "Назва" + msgid "Workspace %d" + msgstr "Робочий простір %d" + ++#: appIcons.js:937 ++#, fuzzy ++msgid "New Window" ++msgstr "" ++"#-#-#-#-# uk.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"Створити вікно\n" ++"#-#-#-#-# uk.po #-#-#-#-#\n" ++"Нове вікно" ++ ++#: prefs.js:213 ++msgid "Running Indicator Options" ++msgstr "Налаштування індикатора роботи" ++ ++#: prefs.js:220 prefs.js:380 prefs.js:445 prefs.js:511 prefs.js:553 ++msgid "Reset to defaults" ++msgstr "Скинути налаштвання" ++ ++#: prefs.js:373 ++msgid "Customize middle-click behavior" ++msgstr "Налаштувати поведінку при середньому кліку" ++ ++#: prefs.js:438 ++msgid "Advanced hotkeys options" ++msgstr "Розширені налаштування гарячих клавіш" ++ ++#: prefs.js:504 ++msgid "Secondary Menu Options" ++msgstr "Налаштування другорядних меню" ++ ++#: prefs.js:546 Settings.ui.h:85 ++msgid "Advanced Options" ++msgstr "Розширені налаштування" ++ ++#: appIcons.js:918 ++msgid "Show Details" ++msgstr "Детальніше" ++ ++#: appIcons.js:937 appIcons.js:998 appIcons.js:1000 Settings.ui.h:8 ++msgid "Quit" ++msgstr "Вийти" ++ ++#: appIcons.js:1000 ++msgid "Windows" ++msgstr "Вікна" ++ ++#: appIcons.js:1159 ++msgid "Dash to Panel Settings" ++msgstr "Налаштування Dash to Panel" ++ ++#: appIcons.js:1166 ++msgid "Restore Windows" ++msgstr "Відновити вікна" ++ ++#: appIcons.js:1166 ++msgid "Show Desktop" ++msgstr "Показати стільницю" ++ ++#: Settings.ui.h:1 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "" ++"За активної опції згортання вікон, подвійне клацання згорне всі вікна " ++"застосунку." ++ ++#: Settings.ui.h:2 ++msgid "Shift+Click action" ++msgstr "Дія при натисканні Shift+Клік" ++ ++#: Settings.ui.h:3 ++msgid "Raise window" ++msgstr "Розгорнути вікно" ++ ++#: Settings.ui.h:4 ++msgid "Minimize window" ++msgstr "Згорнути вікно" ++ ++#: Settings.ui.h:5 ++msgid "Launch new instance" ++msgstr "Запустити нову копію програми" ++ ++#: Settings.ui.h:6 ++msgid "Cycle through windows" ++msgstr "Прокрутка вікон" ++ ++#: Settings.ui.h:7 ++msgid "Cycle windows + minimize" ++msgstr "Прокрутка та згортання вікон" ++ ++#: Settings.ui.h:9 ++msgid "Behavior for Middle-Click." ++msgstr "Поведінка при середньому кліку" ++ ++#: Settings.ui.h:10 ++msgid "Middle-Click action" ++msgstr "Дія при середньому кліку" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Поведінка при Shift+Середній клік" ++ ++#: Settings.ui.h:12 ++msgid "Shift+Middle-Click action" ++msgstr "Дія при Shift+Середній клік" ++ ++#: Settings.ui.h:13 ++msgid "Integrate AppMenu items" ++msgstr "Вбудувати пункти Меню" ++ ++#: Settings.ui.h:14 ++msgid "Show Details menu item" ++msgstr "Пункт меню Детальніше" ++ ++#: Settings.ui.h:15 ++msgid "Highlight focused application" ++msgstr "Підсвічувати застосунок у фокусі" ++ ++#: Settings.ui.h:16 ++msgid "Height (px)" ++msgstr "Висота (пікселів)" ++ ++#: Settings.ui.h:17 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:18 ++msgid "Color - Override Theme" ++msgstr "Колір - Використовувати власну палітру" ++ ++#: Settings.ui.h:19 ++msgid "1 window open" ++msgstr "1 відкрите вікно" ++ ++#: Settings.ui.h:20 ++msgid "Apply to all" ++msgstr "Застосувати для всіх" ++ ++#: Settings.ui.h:21 ++msgid "2 windows open" ++msgstr "2 відкритих вікна" ++ ++#: Settings.ui.h:22 ++msgid "3 windows open" ++msgstr "3 відкритих вікна" ++ ++#: Settings.ui.h:23 ++msgid "4+ windows open" ++msgstr "4 та більше відкритих вікон" ++ ++#: Settings.ui.h:24 ++msgid "Use different for unfocused" ++msgstr "Використовувати інший набір для вікон не у фокусі" ++ ++#: Settings.ui.h:25 ++msgid "Preview timeout on icon leave (ms)" ++msgstr "Показувати ескіз ще (мс) після прибирання курсору миші" ++ ++#: Settings.ui.h:26 ++msgid "" ++"If set too low, the window preview of running applications may seem to close " ++"too quickly when trying to enter the popup. If set too high, the preview may " ++"linger too long when moving to an adjacent icon." ++msgstr "" ++"За надто малих значень ескізи вікон застосунків можуть зникати надто швидко " ++"навіть для спроби переведення курсору з панелі на виринаючий контейнер з " ++"ескізами, але якщо значення зависоке, ескіз може ще довго висіти при " ++"переході на суміжну піктограму." ++ ++#: Settings.ui.h:27 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:28 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:29 ++msgid "Hotkeys prefix" ++msgstr "Префікс гарячих клавіш" ++ ++#: Settings.ui.h:30 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "Гарячі клавіші будуть Super+Число, або Super+Alt+Num" ++ ++#: Settings.ui.h:31 ++msgid "Number overlay" ++msgstr "Комірки з номерами" ++ ++#: Settings.ui.h:32 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "" ++"Тимчасово показувати порядкові номери застосунків над їх піктограмами за " ++"використання гарячих клавіш." ++ ++#: Settings.ui.h:33 ++msgid "Hide timeout (ms)" ++msgstr "Час зникнення (мс)" ++ ++#: Settings.ui.h:34 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "Комбінація для двосекундного показу комірок" ++ ++#: Settings.ui.h:35 ++msgid "Syntax: , , , " ++msgstr "Синтаксис: , , , " ++ ++#: Settings.ui.h:36 ++msgid "Panel screen position" ++msgstr "Розташування панелі на екрані" ++ ++#: Settings.ui.h:37 ++msgid "Bottom" ++msgstr "Знизу" ++ ++#: Settings.ui.h:38 ++msgid "Top" ++msgstr "Вгорі" ++ ++#: Settings.ui.h:39 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"Розмір панелі\n" ++"(48 за замовчуванням)" ++ ++#: Settings.ui.h:41 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"Проміжок між піктограмами\n" ++"(8 за замовчуванням)" ++ ++#: Settings.ui.h:43 ++msgid "Running indicator position" ++msgstr "Розташування індикатора роботи" ++ ++#: Settings.ui.h:44 ++msgid "Running indicator style (Focused app)" ++msgstr "Вигляд індикатора роботи" ++ ++#: Settings.ui.h:45 ++msgid "Dots" ++msgstr "Крапки" ++ ++#: Settings.ui.h:46 ++msgid "Squares" ++msgstr "Квадрати" ++ ++#: Settings.ui.h:47 ++msgid "Dashes" ++msgstr "Рисочки" ++ ++#: Settings.ui.h:48 ++msgid "Segmented" ++msgstr "Сегментований" ++ ++#: Settings.ui.h:49 ++msgid "Solid" ++msgstr "Цільний" ++ ++#: Settings.ui.h:50 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:51 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:52 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "Вигляд індикатора роботи (Не в фокусі)" ++ ++#: Settings.ui.h:53 ++msgid "Clock location" ++msgstr "Розташування годинника" ++ ++#: Settings.ui.h:54 ++msgid "Natural" ++msgstr "За замовчуванням" ++ ++#: Settings.ui.h:55 ++msgid "Left of status menu" ++msgstr "Ліворуч від рядку стану" ++ ++#: Settings.ui.h:56 ++msgid "Right of status menu" ++msgstr "Праворуч від рядку стану" ++ ++#: Settings.ui.h:57 ++msgid "Position and Style" ++msgstr "Стиль і розташування" ++ ++#: Settings.ui.h:58 ++msgid "Show Applications icon" ++msgstr "Піктограма Всі Застосунки" ++ ++#: Settings.ui.h:59 ++msgid "Animate Show Applications." ++msgstr "Анімувати Всі Застосунки." ++ ++#: Settings.ui.h:60 ++msgid "Show Activities button" ++msgstr "Показувати кнопку Діяльність" ++ ++#: Settings.ui.h:61 ++msgid "Show Desktop button" ++msgstr "Показувати кнопку Стільниця" ++ ++#: Settings.ui.h:62 ++msgid "Show AppMenu button" ++msgstr "Показувати кнопку Застосунки" ++ ++#: Settings.ui.h:63 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "" ++"Панель Завдань > Опція \"Показувати Меню Застосунків\" має бути увімкнена у " ++"Tweak Tool" ++ ++#: Settings.ui.h:64 ++msgid "Show window previews on hover" ++msgstr "Показувати виринаючі ескізи вікон при наведенні миші" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "Затримка (мс) перед показом (100 за замовчуванням)" ++ ++#: Settings.ui.h:66 ++msgid "Isolate Workspaces" ++msgstr "Ізолювати стільниці" ++ ++#: Settings.ui.h:67 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "Дія при кліку по піктограмі запущеного застосунку" ++ ++#: Settings.ui.h:68 ++msgid "Click action" ++msgstr "Дія при кліку" ++ ++#: Settings.ui.h:69 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"Зробити Super+(0-9) клавішами швидкого запуску застосунків. Також може " ++"використовуватись з Shift та Ctrl." ++ ++#: Settings.ui.h:70 ++msgid "Use hotkeys to activate apps" ++msgstr "Використовувати гарячі клавіші для запуску улюблених застосунків" ++ ++#: Settings.ui.h:71 ++msgid "Behavior" ++msgstr "Поведінка" ++ ++#: Settings.ui.h:72 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Розмір шрифту у панелі\n" ++"(0 = визначено темою)" ++ ++#: Settings.ui.h:74 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"Розмір шрифту LeftBox\n" ++"(0 = визначено темою)" ++ ++#: Settings.ui.h:76 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Проміжки між об’єктами лотка\n" ++"(-1 = визначено темою)" ++ ++#: Settings.ui.h:78 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Проміжки в рядку стану\n" ++"(-1 = визначено тамою)" ++ ++#: Settings.ui.h:80 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"Проміжок зліва\n" ++"(-1 = визначено темою)" ++ ++#: Settings.ui.h:82 ++msgid "Animate switching applications" ++msgstr "Анімувати перемикання між застосунками" ++ ++#: Settings.ui.h:83 ++msgid "Animate launching new windows" ++msgstr "Анімувати запуск нових вікон" ++ ++#: Settings.ui.h:84 ++msgid "App icon secondary (right-click) menu" ++msgstr "Контекстне меню піктограм застосунків" ++ ++#: Settings.ui.h:86 ++msgid "Fine-Tune" ++msgstr "Тонке налаштування" ++ ++#: Settings.ui.h:87 ++msgid "version: " ++msgstr "версія:" ++ ++#: Settings.ui.h:88 ++msgid "Github" ++msgstr "GitHub" ++ ++#: Settings.ui.h:89 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"Автор програми не надає ЖОДНИХ ГАРАНТІЙ.\n" ++"Перегляньте GNU General Public License, version 2 or later, щоб дізнатися більше." ++"" ++ ++#: Settings.ui.h:91 ++msgid "About" ++msgstr "Про програму" ++ + #~ msgid "GNOME Classic" + #~ msgstr "Класичний GNOME" + +@@ -454,9 +891,6 @@ msgstr "Робочий простір %d" + #~ msgid "Drag here to add favorites" + #~ msgstr "Перетягніть, щоб додати в улюблене" + +-#~ msgid "New Window" +-#~ msgstr "Створити вікно" +- + #~ msgid "Remove from Favorites" + #~ msgstr "Вилучити з улюбленого" + +diff --git a/po/zh_CN.po b/po/zh_CN.po +index adec118b..53a6d876 100644 +--- a/po/zh_CN.po ++++ b/po/zh_CN.po +@@ -348,6 +348,1267 @@ msgstr "名称" + msgid "Workspace %d" + msgstr "工作区 %d" + ++#: Settings.ui.h:145 ++#, fuzzy ++msgid "Left" ++msgstr "" ++"#-#-#-#-# zh_CN.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"左\n" ++"#-#-#-#-# zh_CN.po (dash-to-panel 24) #-#-#-#-#\n" ++"左侧" ++ ++#: Settings.ui.h:146 ++#, fuzzy ++msgid "Right" ++msgstr "" ++"#-#-#-#-# zh_CN.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"右\n" ++"#-#-#-#-# zh_CN.po (dash-to-panel 24) #-#-#-#-#\n" ++"右侧" ++ ++#: appIcons.js:1398 ++#, fuzzy ++msgid "New Window" ++msgstr "" ++"#-#-#-#-# zh_CN.po (gnome-shell-extensions master) #-#-#-#-#\n" ++"新窗口\n" ++"#-#-#-#-# zh_CN.po (dash-to-panel 24) #-#-#-#-#\n" ++"新建窗口" ++ ++#: prefs.js:211 ++msgid "Top, with plugin icons collapsed to bottom" ++msgstr "顶部,并且插件图标收缩到底部" ++ ++#: prefs.js:211 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "左侧,并且插件图标收缩到右侧" ++ ++#: prefs.js:212 ++msgid "Top, with fixed center plugin icons" ++msgstr "顶部,并且固定居中插件图标" ++ ++#: prefs.js:212 ++msgid "Left, with fixed center plugin icons" ++msgstr "左侧,并且固定居中插件图标" ++ ++#: prefs.js:213 ++msgid "Top, with floating center plugin icons" ++msgstr "顶部,并且浮动居中插件图标" ++ ++#: prefs.js:213 ++msgid "Left, with floating center plugin icons" ++msgstr "左侧,并且浮动居中插件图标" ++ ++#: prefs.js:214 ++msgid "Center, fixed in middle of monitor" ++msgstr "中间,固定在显示屏中间" ++ ++#: prefs.js:215 ++msgid "Center, floating between top and bottom elements" ++msgstr "中间,在顶部元素和底部元素之间浮动" ++ ++#: prefs.js:215 ++msgid "Center, floating between left and right elements" ++msgstr "中间,在左侧元素和右侧元素之间浮动" ++ ++#: prefs.js:219 ++msgid "Top of plugin icons" ++msgstr "插件图标上侧" ++ ++#: prefs.js:219 ++msgid "Left of plugin icons" ++msgstr "插件图标左侧" ++ ++#: prefs.js:220 ++msgid "Bottom of plugin icons" ++msgstr "插件图标下侧" ++ ++#: prefs.js:220 ++msgid "Right of plugin icons" ++msgstr "插件图标右侧" ++ ++#: prefs.js:221 ++msgid "Top of system indicators" ++msgstr "系统指示器上侧" ++ ++#: prefs.js:221 ++msgid "Left of system indicators" ++msgstr "系统指示器左侧" ++ ++#: prefs.js:222 ++msgid "Bottom of system indicators" ++msgstr "系统指示器下侧" ++ ++#: prefs.js:222 ++msgid "Right of system indicators" ++msgstr "系统指示器右侧" ++ ++#: prefs.js:223 ++msgid "Top of taskbar" ++msgstr "任务栏上侧" ++ ++#: prefs.js:223 ++msgid "Left of taskbar" ++msgstr "任务栏左侧" ++ ++#: prefs.js:224 ++msgid "Bottom of taskbar" ++msgstr "任务栏下侧" ++ ++#: prefs.js:224 ++msgid "Right of taskbar" ++msgstr "任务栏右侧" ++ ++#: prefs.js:230 ++msgid "Show Desktop button height (px)" ++msgstr "“显示桌面”按钮图标高度(像素)" ++ ++#: prefs.js:230 ++msgid "Show Desktop button width (px)" ++msgstr "“显示桌面”按钮图标宽度(像素)" ++ ++#: prefs.js:364 ++msgid "Running Indicator Options" ++msgstr "运行指示器选项" ++ ++#: prefs.js:371 prefs.js:569 prefs.js:712 prefs.js:837 prefs.js:904 ++#: prefs.js:992 prefs.js:1078 prefs.js:1325 prefs.js:1409 prefs.js:1474 ++#: prefs.js:1510 prefs.js:1607 prefs.js:1641 prefs.js:1683 ++msgid "Reset to defaults" ++msgstr "恢复默认值" ++ ++#: prefs.js:514 ++msgid "Default (Primary monitor)" ++msgstr "主显示器" ++ ++#: prefs.js:517 ++msgid "Monitor " ++msgstr "显示器 " ++ ++#: prefs.js:562 ++msgid "Multi-monitors options" ++msgstr "多显示器选项" ++ ++#: prefs.js:705 ++msgid "Dynamic opacity options" ++msgstr "动态半透明选项" ++ ++#: prefs.js:830 ++msgid "Intellihide options" ++msgstr "智能隐藏选项" ++ ++#: prefs.js:897 ++msgid "Show Applications options" ++msgstr "“显示应用程序”选项" ++ ++#: prefs.js:985 ++msgid "Show Desktop options" ++msgstr "“显示桌面”选项" ++ ++#: prefs.js:1071 ++msgid "Window preview options" ++msgstr "窗口预览选项" ++ ++#: prefs.js:1318 ++msgid "Ungrouped application options" ++msgstr "未分组的应用程序选项" ++ ++#: prefs.js:1402 ++msgid "Customize middle-click behavior" ++msgstr "自定义中键点击行为" ++ ++#: prefs.js:1467 ++msgid "Customize panel scroll behavior" ++msgstr "自定义面板滚动行为" ++ ++#: prefs.js:1503 ++msgid "Customize icon scroll behavior" ++msgstr "自定义图标滚动行为" ++ ++#: prefs.js:1600 ++msgid "Advanced hotkeys options" ++msgstr "高级热键选项" ++ ++#: prefs.js:1634 ++msgid "Secondary Menu Options" ++msgstr "次级菜单选项" ++ ++#: prefs.js:1676 Settings.ui.h:223 ++msgid "Advanced Options" ++msgstr "高级选项" ++ ++#: prefs.js:1763 ++msgid "Export settings" ++msgstr "导出设置" ++ ++#: prefs.js:1780 ++msgid "Import settings" ++msgstr "导入设置" ++ ++#: appIcons.js:1380 ++msgid "Show Details" ++msgstr "显示细节" ++ ++#: appIcons.js:1398 appIcons.js:1458 appIcons.js:1460 Settings.ui.h:10 ++msgid "Quit" ++msgstr "退出" ++ ++#: appIcons.js:1460 ++msgid "Windows" ++msgstr "窗口" ++ ++#: appIcons.js:1684 ++msgid "Power options" ++msgstr "电源选项" ++ ++#: appIcons.js:1689 ++msgid "Event logs" ++msgstr "事件日志" ++ ++#: appIcons.js:1694 ++msgid "System" ++msgstr "系统" ++ ++#: appIcons.js:1699 ++msgid "Device Management" ++msgstr "设备管理" ++ ++#: appIcons.js:1704 ++msgid "Disk Management" ++msgstr "磁盘管理" ++ ++#: appIcons.js:1711 ++msgid "Terminal" ++msgstr "终端" ++ ++#: appIcons.js:1716 ++msgid "System monitor" ++msgstr "系统监视器" ++ ++#: appIcons.js:1721 ++msgid "Files" ++msgstr "文件" ++ ++#: appIcons.js:1726 ++msgid "Settings" ++msgstr "导出设置设置" ++ ++#: appIcons.js:1733 ++msgid "Unlock taskbar" ++msgstr "解锁任务栏" ++ ++#: appIcons.js:1733 ++msgid "Lock taskbar" ++msgstr "锁定任务栏" ++ ++#: appIcons.js:1738 ++msgid "Dash to Panel Settings" ++msgstr "Dash to Panel 设置" ++ ++#: appIcons.js:1745 ++msgid "Restore Windows" ++msgstr "恢复窗口" ++ ++#: appIcons.js:1745 ++msgid "Show Desktop" ++msgstr "显示桌面" ++ ++#: update.js:58 ++#, javascript-format ++msgid "Version %s (%s) is available" ++msgstr "版本 %s(%s)已经可用" ++ ++#: update.js:59 ++msgid "Details" ++msgstr "详细信息" ++ ++#: update.js:60 ++msgid "Update" ++msgstr "更新" ++ ++#: update.js:63 ++msgid "Already up to date" ++msgstr "已经处于最新状态" ++ ++#: update.js:148 ++msgid "Update successful, please log out/in" ++msgstr "更新成功,请注销并重新登录" ++ ++#: update.js:149 ++msgid "Log out" ++msgstr "注销" ++ ++#: update.js:153 ++msgid "Update successful, please restart GNOME Shell" ++msgstr "更新成功,请重新启动 GNOME Shell" ++ ++#: update.js:154 ++msgid "Restart GNOME Shell" ++msgstr "重新启动 GNOME Shell" ++ ++#: update.js:154 ++msgid "Restarting GNOME Shell..." ++msgstr "正在重新启动 GNOME Shell……" ++ ++#: update.js:160 ++msgid "Error: " ++msgstr "错误:" ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "暂时什么都没有!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "设置为最小化时,双击将最小化该应用程序的所有窗口。" ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Shift+点击动作" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "提升窗口" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "最小化窗口" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "启动新实例" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "在窗口间循环切换" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "循环窗口 + 最小化" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "切换单个 / 预览多个" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "中键点击行为。" ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "中键点击动作" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Shift+中键点击的行为。" ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Shift+中键点击动作" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "隔离显示器" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "在所有显示器上显示收藏的应用程序" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "在所有显示器上显示时钟" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "在所有显示器上显示状态菜单" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "集成应用菜单项" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "显示细节菜单项" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "高亮显示取得焦点的应用程序" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "图标主颜色" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "自定义颜色" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "高亮不透明度" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "指示器高度(像素)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "指示器颜色 - 图标主色" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "指示器颜色 - 覆盖主题" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "1 窗口开启(或未分组)" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "应用至全部" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "2 窗口开启" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "3 窗口开启" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "4+ 窗口开启" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "为未取得焦点的程序使用不同方案" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "应用程序标题字体大小(像素)(默认值为 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "应用程序标题字体粗细" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "继承自主题" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "正常" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "较细" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "粗体" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "更粗" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "应用程序标题字体颜色" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "应用程序最大宽度(像素)(默认值为 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "为应用程序标题使用固定宽度" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"应用程序标题都将使用相同宽度,即使其文本宽度无法达到最大宽度。最大宽度值将被" ++"用于固定宽度值。" ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "在未取得焦点的应用上显示运行指示器" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "使用收藏的图标作为应用程序启动器" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "仅在面板被窗口阻挡时隐藏 " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "触发面板隐藏的对象" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "所有窗口" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "获得焦点的窗口" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "最大化窗口" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "在屏幕边缘受到一定光标压力时显示面板" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "所需压力阈值(像素)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "所需压力超时(毫秒)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "允许面板在全屏幕模式下显示" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "只隐藏次要面板(需要多显示器选项)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "例如 i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "显示并保持面板的键盘快捷键" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "语法:, , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "隐藏与显示动画持续时间(毫秒)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "隐藏面板之前的延时(毫秒)" ++ ++#: Settings.ui.h:62 ++msgid "Delay before enabling intellihide on start (ms)" ++msgstr "启动后到启用智能隐藏之间的延时(毫秒)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "显示前的延时(毫秒,默认为 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "动画时间(毫秒)" ++ ++#: Settings.ui.h:65 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "隐藏前的延时(毫秒,默认为 100)" ++ ++#: Settings.ui.h:66 ++msgid "Immediate on application icon click" ++msgstr "点击应用程序图标后立即触发" ++ ++#: Settings.ui.h:67 ++msgid "Middle click on the preview to close the window" ++msgstr "在预览上中键点击以关闭窗口" ++ ++#: Settings.ui.h:68 ++msgid "Window previews preferred size (px)" ++msgstr "窗口预览偏好大小(像素)" ++ ++#: Settings.ui.h:69 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "窗口预览长宽比 X(高度)" ++ ++#: Settings.ui.h:70 ++msgid "Window previews padding (px)" ++msgstr "窗口预览填充距离(像素)" ++ ++#: Settings.ui.h:71 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:72 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:73 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:74 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:75 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:76 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:77 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:78 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:79 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:80 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:81 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:82 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:83 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:84 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:85 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:86 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:87 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:88 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:89 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:90 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:91 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:92 ++msgid "Fixed" ++msgstr "固定" ++ ++#: Settings.ui.h:93 ++msgid "Window previews aspect ratio X (width)" ++msgstr "窗口预览长宽比 X(宽度)" ++ ++#: Settings.ui.h:94 ++msgid "Use custom opacity for the previews background" ++msgstr "为预览背景使用自定义不透明度" ++ ++#: Settings.ui.h:95 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "如果禁用,预览的背景与面板的不透明度将保持一致" ++ ++#: Settings.ui.h:96 ++msgid "Close button and header position" ++msgstr "关闭按钮和头部的位置" ++ ++#: Settings.ui.h:97 ++msgid "Bottom" ++msgstr "底部" ++ ++#: Settings.ui.h:98 ++msgid "Top" ++msgstr "顶部" ++ ++#: Settings.ui.h:99 ++msgid "Display window preview headers" ++msgstr "显示窗口预览头部" ++ ++#: Settings.ui.h:100 ++msgid "Font size (px) of the preview titles" ++msgstr "预览标题的字体大小(像素)" ++ ++#: Settings.ui.h:101 ++msgid "Font weight of the preview titles" ++msgstr "预览标题的字重" ++ ++#: Settings.ui.h:102 ++msgid "Font color of the preview titles" ++msgstr "预览标题的字体颜色" ++ ++#: Settings.ui.h:103 ++msgid "Enable window peeking" ++msgstr "启用窗口概览功能" ++ ++#: Settings.ui.h:104 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "在窗口预览上悬浮一定时间后,该窗口将被区别显示。" ++ ++#: Settings.ui.h:105 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "进入窗口概览模式延时(毫秒)" ++ ++#: Settings.ui.h:106 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:107 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "为进入窗口概览模式,需要光标悬浮在预览窗口上不活动的时间。" ++ ++#: Settings.ui.h:108 ++msgid "Window peeking mode opacity" ++msgstr "窗口概览模式不透明度" ++ ++#: Settings.ui.h:109 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:110 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "除正在处于概览状态的窗口外,其它所有窗口的不透明度将被设置为同一个值。" ++ ++#: Settings.ui.h:111 ++msgid "Delay between mouse scroll events (ms)" ++msgstr "鼠标滚动事件之间的延迟(毫秒)" ++ ++#: Settings.ui.h:112 ++msgid "Use this value to limit the number of captured mouse scroll events." ++msgstr "使用这个值来限制对鼠标滚动事件捕捉的频率。" ++ ++#: Settings.ui.h:113 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:114 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:115 ++msgid "Hotkeys prefix" ++msgstr "热键前缀" ++ ++#: Settings.ui.h:116 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "热键可以是 Super+数字 或者 Super+Alt+数字" ++ ++#: Settings.ui.h:117 ++msgid "Never" ++msgstr "从不" ++ ++#: Settings.ui.h:118 ++msgid "Show temporarily" ++msgstr "暂时显示" ++ ++#: Settings.ui.h:119 ++msgid "Always visible" ++msgstr "总是可见" ++ ++#: Settings.ui.h:120 ++msgid "Number overlay" ++msgstr "数字附加显示" ++ ++#: Settings.ui.h:121 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "使用热键时在应用图标上临时显示其对应数字。" ++ ++#: Settings.ui.h:122 ++msgid "Hide timeout (ms)" ++msgstr "隐藏延时(毫秒)" ++ ++#: Settings.ui.h:123 ++msgid "e.g. q" ++msgstr "例如 q" ++ ++#: Settings.ui.h:124 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "显示两秒钟附加数字的快捷键" ++ ++#: Settings.ui.h:125 ++msgid "Show window previews on hotkey" ++msgstr "按下热键时显示窗口预览" ++ ++#: Settings.ui.h:126 ++msgid "Show previews when the application have multiple instances" ++msgstr "应用程序有多个实例时显示预览" ++ ++#: Settings.ui.h:127 ++msgid "Number row" ++msgstr "键盘主数字行" ++ ++#: Settings.ui.h:128 ++msgid "Numeric keypad" ++msgstr "数字小键盘" ++ ++#: Settings.ui.h:129 ++msgid "Both" ++msgstr "两者" ++ ++#: Settings.ui.h:130 ++msgid "Hotkeys are activated with" ++msgstr "热键激活来源" ++ ++#: Settings.ui.h:131 ++msgid "Select which keyboard number keys are used to activate the hotkeys" ++msgstr "选择用于激活热键的键盘数字键" ++ ++#: Settings.ui.h:132 ++msgid "Current Show Applications icon" ++msgstr "当前“显示应用程序”图标" ++ ++#: Settings.ui.h:133 ++msgid "Select a Show Applications image icon" ++msgstr "选择一个“显示应用程序”图标图像" ++ ++#: Settings.ui.h:134 ++msgid "Custom Show Applications image icon" ++msgstr "自定义“显示应用程序”图标图像" ++ ++#: Settings.ui.h:135 ++msgid "Show Applications icon side padding (px)" ++msgstr "“显示应用程序”图标侧边距(像素)" ++ ++#: Settings.ui.h:136 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "悬停在显示桌面按钮时展示桌面预览" ++ ++#: Settings.ui.h:137 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "展示桌面预览之前的延时(毫秒)" ++ ++#: Settings.ui.h:138 ++msgid "Fade duration (ms)" ++msgstr "淡出延时(毫秒)" ++ ++#: Settings.ui.h:139 ++msgid "The panel background opacity is affected by" ++msgstr "面板背景不透明度的影响因素" ++ ++#: Settings.ui.h:140 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "在窗口多靠近时修改不透明度(像素 px)" ++ ++#: Settings.ui.h:142 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "将不透明度修改为(%)" ++ ++#: Settings.ui.h:143 ++msgid "Opacity change animation duration (ms)" ++msgstr "不透明度变更动画持续时间(毫秒)" ++ ++#: Settings.ui.h:144 ++msgid "Panel screen position" ++msgstr "面板屏幕位置" ++ ++#: Settings.ui.h:147 ++msgid "Taskbar position" ++msgstr "任务栏位置" ++ ++#: Settings.ui.h:148 ++msgid "Clock location" ++msgstr "时钟位置" ++ ++#: Settings.ui.h:149 ++msgid "Display the main panel on" ++msgstr "将主面板显示于" ++ ++#: Settings.ui.h:150 ++msgid "Display panels on all monitors" ++msgstr "在所有显示器上显示面板" ++ ++#: Settings.ui.h:151 ++msgid "Panel Intellihide" ++msgstr "面板智能隐藏" ++ ++#: Settings.ui.h:152 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "按照配置隐藏和显示面板" ++ ++#: Settings.ui.h:153 ++msgid "Position" ++msgstr "位置" ++ ++#: Settings.ui.h:154 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"面板大小\n" ++"(默认为 48)" ++ ++#: Settings.ui.h:156 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"应用图标边缘空白\n" ++"(默认为 8)" ++ ++#: Settings.ui.h:158 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"应用图标边缘空白\n" ++"(默认为 4)" ++ ++#: Settings.ui.h:160 ++msgid "Running indicator position" ++msgstr "运行指示器位置" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator style (Focused app)" ++msgstr "运行指示器风格(取得焦点的应用)" ++ ++#: Settings.ui.h:162 ++msgid "Dots" ++msgstr "点" ++ ++#: Settings.ui.h:163 ++msgid "Squares" ++msgstr "方块" ++ ++#: Settings.ui.h:164 ++msgid "Dashes" ++msgstr "横线" ++ ++#: Settings.ui.h:165 ++msgid "Segmented" ++msgstr "间断线" ++ ++#: Settings.ui.h:166 ++msgid "Solid" ++msgstr "实心" ++ ++#: Settings.ui.h:167 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:168 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:169 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "运行指示器风格(未取得焦点的应用)" ++ ++#: Settings.ui.h:170 ++msgid "Override panel theme background color " ++msgstr "覆盖面板主题背景颜色 " ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background opacity" ++msgstr "覆盖面板主题背景不透明度" ++ ++#: Settings.ui.h:173 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "面板背景不透明度(%)" ++ ++#: Settings.ui.h:174 ++msgid "Dynamic background opacity" ++msgstr "动态背景不透明度" ++ ++#: Settings.ui.h:175 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "在有窗口接近面板时修改不透明度" ++ ++#: Settings.ui.h:176 ++msgid "Override panel theme gradient " ++msgstr "覆盖面板主题渐变 " ++ ++#: Settings.ui.h:178 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "渐变顶部颜色和不透明度(%)" ++ ++#: Settings.ui.h:180 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "渐变底部颜色和不透明度(%)" ++ ++#: Settings.ui.h:181 ++msgid "Style" ++msgstr "风格" ++ ++#: Settings.ui.h:182 ++msgid "Show favorite applications" ++msgstr "显示收藏的应用程序" ++ ++#: Settings.ui.h:183 ++msgid "Show running applications" ++msgstr "显示正在运行的应用程序" ++ ++#: Settings.ui.h:184 ++msgid "Show Applications icon" ++msgstr "显示应用图标" ++ ++#: Settings.ui.h:185 ++msgid "Animate Show Applications." ++msgstr "动画化显示应用程序。" ++ ++#: Settings.ui.h:186 ++msgid "Show Activities button" ++msgstr "显示活动按钮" ++ ++#: Settings.ui.h:187 ++msgid "Show Desktop button" ++msgstr "显示桌面按钮" ++ ++#: Settings.ui.h:188 ++msgid "Show AppMenu button" ++msgstr "显示应用菜单按钮" ++ ++#: Settings.ui.h:189 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "必须在优化工具中启用顶栏 > 显示应用菜单" ++ ++#: Settings.ui.h:190 ++msgid "Show window previews on hover" ++msgstr "悬停时显示窗口预览" ++ ++#: Settings.ui.h:191 ++msgid "Show tooltip on hover" ++msgstr "悬停时显示工具提示" ++ ++#: Settings.ui.h:192 ++msgid "Isolate Workspaces" ++msgstr "隔离工作区" ++ ++#: Settings.ui.h:193 ++msgid "Ungroup applications" ++msgstr "取消应用程序分组" ++ ++#: Settings.ui.h:194 ++msgid "Behavior" ++msgstr "行为" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "点击正在运行应用程序图标时的行为。" ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "点击行为" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "切换窗口" ++ ++#: Settings.ui.h:198 ++msgid "Scroll panel action" ++msgstr "滚动面板行为" ++ ++#: Settings.ui.h:199 ++msgid "Behavior when mouse scrolling over the panel." ++msgstr "在面板上滚动鼠标滚轮时的行为。" ++ ++#: Settings.ui.h:200 ++msgid "Scroll icon action" ++msgstr "滚动行为" ++ ++#: Settings.ui.h:201 ++msgid "Behavior when mouse scrolling over an application icon." ++msgstr "在正在运行应用程序图标上滚动鼠标滚轮时的行为。" ++ ++#: Settings.ui.h:202 ++msgid "Do nothing" ++msgstr "什么也不做" ++ ++#: Settings.ui.h:203 ++msgid "Switch workspace" ++msgstr "切换工作区" ++ ++#: Settings.ui.h:204 ++msgid "Cycle windows" ++msgstr "循环窗口" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"将 Super+(0-9) 作为激活应用程序的快捷键。它也可以和 Shift 或 Ctrl 共同使用。" ++ ++#: Settings.ui.h:206 ++msgid "Use hotkeys to activate apps" ++msgstr "使用热键激活应用" ++ ++#: Settings.ui.h:207 ++msgid "Action" ++msgstr "行为" ++ ++#: Settings.ui.h:208 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"托盘字体大小\n" ++"(0 = 主题默认)" ++ ++#: Settings.ui.h:210 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"LeftBox 字体大小\n" ++"(0 = 主题默认)" ++ ++#: Settings.ui.h:212 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"托盘项边缘空白\n" ++"(-1 = 主题默认)" ++ ++#: Settings.ui.h:214 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"状态图标边缘空白\n" ++"(-1 = 主题默认)" ++ ++#: Settings.ui.h:216 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"LeftBox 边缘空白\n" ++"(-1 = 主题默认)" ++ ++#: Settings.ui.h:218 ++msgid "Animate switching applications" ++msgstr "动画切换应用程序" ++ ++#: Settings.ui.h:219 ++msgid "Animate launching new windows" ++msgstr "动画启动新窗口" ++ ++#: Settings.ui.h:220 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "保持原始 gnome-shell dash(预览)" ++ ++#: Settings.ui.h:221 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "只在点击时激活面板菜单按钮(例如:日期菜单)" ++ ++#: Settings.ui.h:222 ++msgid "App icon secondary (right-click) menu" ++msgstr "应用图标次级(右键点击)菜单" ++ ++#: Settings.ui.h:224 ++msgid "Fine-Tune" ++msgstr "微调" ++ ++#: Settings.ui.h:225 ++msgid "version: " ++msgstr "版本:" ++ ++#: Settings.ui.h:226 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:227 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"使用下面的按钮以基于您当前的首选项创建一个设置文件;您稍后可使用该文件在其他" ++"机器上导入设置。" ++ ++#: Settings.ui.h:228 ++msgid "Export and import settings" ++msgstr "导入导出设置" ++ ++#: Settings.ui.h:229 ++msgid "Export to file" ++msgstr "导出至文件" ++ ++#: Settings.ui.h:230 ++msgid "Import from file" ++msgstr "从文件导入" ++ ++#: Settings.ui.h:231 ++msgid "" ++"This allows you to update the extension directly from the GitHub repository." ++msgstr "这样可以帮助您直接从 GitHub 仓库更新本扩展。" ++ ++#: Settings.ui.h:232 ++msgid "Updates" ++msgstr "更新" ++ ++#: Settings.ui.h:233 ++msgid "Periodically check for updates" ++msgstr "定期检查更新" ++ ++#: Settings.ui.h:234 ++msgid "Check now" ++msgstr "立刻检查" ++ ++#: Settings.ui.h:235 ++msgid "" ++"Be aware, these official Dash to " ++"Panel releases might not be reviewed yet on extensions.gnome.org! Read more" ++msgstr "" ++"请注意,这些官方发布的 Dash to Panel " ++"版本可能还没有通过 extensions.gnome.org 的审查! 详细了解" ++ ++#: Settings.ui.h:236 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"本程序不提供任何担保。\n" ++"请查看 GNU 通用公共许可证,第二版或更新版本 以了解详情。" ++ ++#: Settings.ui.h:238 ++msgid "About" ++msgstr "关于" ++ + #~ msgid "GNOME Shell Classic" + #~ msgstr "GNOME Shell 经典模式" + +@@ -384,12 +1645,6 @@ msgstr "工作区 %d" + #~ msgid "Normal" + #~ msgstr "正常" + +-#~ msgid "Left" +-#~ msgstr "左" +- +-#~ msgid "Right" +-#~ msgstr "右" +- + #~ msgid "Upside-down" + #~ msgstr "上下翻转" + +@@ -413,9 +1668,6 @@ msgstr "工作区 %d" + #~ msgid "Drag here to add favorites" + #~ msgstr "拖放到这里以添加收藏" + +-#~ msgid "New Window" +-#~ msgstr "新窗口" +- + #~ msgid "Quit Application" + #~ msgstr "退出应用程序" + +@@ -568,3 +1820,41 @@ msgstr "工作区 %d" + + #~ msgid "Busy" + #~ msgstr "忙碌" ++ ++#~ msgid "Highlight color" ++#~ msgstr "高亮颜色" ++ ++#~ msgid "Preview timeout on icon leave (ms)" ++#~ msgstr "离开图标时的预览延时(毫秒)" ++ ++#~ msgid "" ++#~ "If set too low, the window preview of running applications may seem to " ++#~ "close too quickly when trying to enter the popup. If set too high, the " ++#~ "preview may linger too long when moving to an adjacent icon." ++#~ msgstr "" ++#~ "如果设置过低,在尝试进入弹出菜单时正在运行程序的窗口预览可能会关闭得过快。" ++#~ "如果设置过高,在移动至临接图标时预览可能滞留过长时间。" ++ ++#~ msgid "Middle click to close window" ++#~ msgstr "中键点击以关闭窗口" ++ ++#~ msgid "Width of the window previews (px)" ++#~ msgstr "窗口预览宽度(像素)" ++ ++#~ msgid "Height of the window previews (px)" ++#~ msgstr "窗口预览高度(像素)" ++ ++#~ msgid "Padding of the window previews (px)" ++#~ msgstr "窗口预览边缘宽度(像素)" ++ ++#~ msgid "Natural" ++#~ msgstr "自然" ++ ++#~ msgid "Left side of panel" ++#~ msgstr "面板左侧" ++ ++#~ msgid "Centered in content" ++#~ msgstr "内容居中" ++ ++#~ msgid "Github" ++#~ msgstr "Github" +diff --git a/po/zh_TW.po b/po/zh_TW.po +index fa5ba9b8..015d85a4 100644 +--- a/po/zh_TW.po ++++ b/po/zh_TW.po +@@ -435,7 +435,7 @@ msgstr "開啟終端器" + msgid "Change Background…" + msgstr "變更背景圖片…" + +-#: desktopGrid.js:308 ++#: desktopGrid.js:308 appIcons.js:1620 + msgid "Settings" + msgstr "設定" + +@@ -487,6 +487,1057 @@ msgstr "顯示垃圾桶圖示" + msgid "Show the trash icon in the desktop." + msgstr "在桌面顯示垃圾桶圖示。" + ++#: appIcons.js:1306 ++#, fuzzy ++msgid "New Window" ++msgstr "" ++"#-#-#-#-# zh_TW.po (gnome-shell-extensions gnome-3-0) #-#-#-#-#\n" ++"新視窗\n" ++"#-#-#-#-# zh_TW.po (Dash To Panel) #-#-#-#-#\n" ++"建立視窗" ++ ++#: prefs.js:310 ++msgid "Running Indicator Options" ++msgstr "執行指示器選項" ++ ++#: prefs.js:317 prefs.js:515 prefs.js:658 prefs.js:778 prefs.js:842 ++#: prefs.js:930 prefs.js:1023 prefs.js:1260 prefs.js:1344 prefs.js:1455 ++#: prefs.js:1489 prefs.js:1531 ++msgid "Reset to defaults" ++msgstr "重設至預設值" ++ ++#: prefs.js:460 ++msgid "Default (Primary monitor)" ++msgstr "預設(主顯示器)" ++ ++#: prefs.js:463 ++msgid "Monitor " ++msgstr "顯示器 " ++ ++#: prefs.js:508 ++msgid "Multi-monitors options" ++msgstr "多顯示器選項" ++ ++#: prefs.js:651 ++msgid "Dynamic opacity options" ++msgstr "動態半透明選項" ++ ++#: prefs.js:771 ++msgid "Intellihide options" ++msgstr "智慧隱藏選項" ++ ++#: prefs.js:835 ++msgid "Show Applications options" ++msgstr "“顯示應用程式”選項" ++ ++#: prefs.js:923 ++msgid "Show Desktop options" ++msgstr "“顯示桌面”選項" ++ ++#: prefs.js:1016 ++msgid "Window preview options" ++msgstr "視窗預覽選項" ++ ++#: prefs.js:1253 ++msgid "Ungrouped application options" ++msgstr "未分組的應用程式選項" ++ ++#: prefs.js:1337 ++msgid "Customize middle-click behavior" ++msgstr "自訂滑鼠中鍵點選行為" ++ ++#: prefs.js:1448 ++msgid "Advanced hotkeys options" ++msgstr "進階快速鍵選項" ++ ++#: prefs.js:1482 ++msgid "Secondary Menu Options" ++msgstr "次級選單選項" ++ ++#: prefs.js:1524 ++msgid "Advanced Options" ++msgstr "進階選項" ++ ++#: prefs.js:1611 ++msgid "Export settings" ++msgstr "匯出設定" ++ ++#: prefs.js:1628 ++msgid "Import settings" ++msgstr "匯入設定" ++ ++#: appIcons.js:1287 ++msgid "Show Details" ++msgstr "顯示詳細資訊" ++ ++#: appIcons.js:1306 appIcons.js:1368 appIcons.js:1370 ++msgid "Quit" ++msgstr "離開" ++ ++#: appIcons.js:1370 ++msgid "Windows" ++msgstr "視窗" ++ ++#: appIcons.js:1578 ++msgid "Power options" ++msgstr "電源選項" ++ ++#: appIcons.js:1583 ++msgid "Event logs" ++msgstr "事件日誌" ++ ++#: appIcons.js:1588 ++msgid "System" ++msgstr "系統" ++ ++#: appIcons.js:1593 ++msgid "Device Management" ++msgstr "裝置管理" ++ ++#: appIcons.js:1598 ++msgid "Disk Management" ++msgstr "磁碟管理" ++ ++#: appIcons.js:1605 ++msgid "Terminal" ++msgstr "終端" ++ ++#: appIcons.js:1610 ++msgid "System monitor" ++msgstr "系統監視器" ++ ++#: appIcons.js:1615 ++msgid "Files" ++msgstr "檔案" ++ ++#: appIcons.js:1627 ++msgid "Unlock taskbar" ++msgstr "解鎖工作列" ++ ++#: appIcons.js:1627 ++msgid "Lock taskbar" ++msgstr "鎖定工作列" ++ ++#: appIcons.js:1632 ++msgid "Dash to Panel Settings" ++msgstr "Dash to Panel 設定" ++ ++#: appIcons.js:1639 ++msgid "Restore Windows" ++msgstr "復原視窗" ++ ++#: appIcons.js:1639 ++msgid "Show Desktop" ++msgstr "顯示桌面" ++ ++#: Settings.ui.h:1 ++msgid "Nothing yet!" ++msgstr "這裏什麼也沒有!" ++ ++#: Settings.ui.h:2 ++msgid "" ++"When set to minimize, double clicking minimizes all the windows of the " ++"application." ++msgstr "當設定為最小化時,點兩下可將應用程式的所有視窗最小化。" ++ ++#: Settings.ui.h:3 ++msgid "Shift+Click action" ++msgstr "Shift + 點選動作" ++ ++#: Settings.ui.h:4 ++msgid "Raise windows" ++msgstr "抬升視窗" ++ ++#: Settings.ui.h:5 ++msgid "Minimize window" ++msgstr "最小化視窗" ++ ++#: Settings.ui.h:6 ++msgid "Launch new instance" ++msgstr "啟動新實例" ++ ++#: Settings.ui.h:7 ++msgid "Cycle through windows" ++msgstr "在視窗間循環" ++ ++#: Settings.ui.h:8 ++msgid "Cycle windows + minimize" ++msgstr "循環視窗並最小化" ++ ++#: Settings.ui.h:9 ++msgid "Toggle single / Preview multiple" ++msgstr "切換單視窗 / 預覽多視窗" ++ ++#: Settings.ui.h:11 ++msgid "Behavior for Middle-Click." ++msgstr "滑鼠中鍵行為。" ++ ++#: Settings.ui.h:12 ++msgid "Middle-Click action" ++msgstr "滑鼠中鍵動作" ++ ++#: Settings.ui.h:13 ++msgid "Behavior for Shift+Middle-Click." ++msgstr "Shift + 滑鼠中鍵行為。" ++ ++#: Settings.ui.h:14 ++msgid "Shift+Middle-Click action" ++msgstr "Shift + 滑鼠中鍵動作" ++ ++#: Settings.ui.h:15 ++msgid "Isolate monitors" ++msgstr "隔離顯示器" ++ ++#: Settings.ui.h:16 ++msgid "Display favorite applications on all monitors" ++msgstr "在所有顯示器上顯示收藏的應用程式" ++ ++#: Settings.ui.h:17 ++msgid "Display the clock on all monitors" ++msgstr "在所有顯示器上顯示時鐘" ++ ++#: Settings.ui.h:18 ++msgid "Display the status menu on all monitors" ++msgstr "在所有顯示器上顯示狀態選單" ++ ++#: Settings.ui.h:19 ++msgid "Integrate AppMenu items" ++msgstr "整合 AppMenu 項目" ++ ++#: Settings.ui.h:20 ++msgid "Show Details menu item" ++msgstr "顯示詳細資料 選單項目" ++ ++#: Settings.ui.h:21 ++msgid "Highlight focused application" ++msgstr "突顯焦點應用" ++ ++#: Settings.ui.h:22 ++msgid "Icon dominant color" ++msgstr "圖示主色" ++ ++#: Settings.ui.h:23 ++msgid "Custom color" ++msgstr "自訂顏色" ++ ++#: Settings.ui.h:24 ++msgid "Highlight opacity" ++msgstr "突顯不透明度" ++ ++#: Settings.ui.h:25 ++msgid "Indicator height (px)" ++msgstr "指示器高度(像素 px)" ++ ++#: Settings.ui.h:26 ++msgid "Indicator color - Icon Dominant" ++msgstr "指示器顏色 - 主圖示" ++ ++#: Settings.ui.h:27 ++msgid "Indicator color - Override Theme" ++msgstr "指示器顏色 - 覆寫主題" ++ ++#: Settings.ui.h:28 ++msgid "1 window open (or ungrouped)" ++msgstr "打開了(或未分組)1 個視窗" ++ ++#: Settings.ui.h:29 ++msgid "Apply to all" ++msgstr "全部套用" ++ ++#: Settings.ui.h:30 ++msgid "2 windows open" ++msgstr "打開了 2 個視窗" ++ ++#: Settings.ui.h:31 ++msgid "3 windows open" ++msgstr "打開了 3 個視窗" ++ ++#: Settings.ui.h:32 ++msgid "4+ windows open" ++msgstr "打開了 4 個以上的視窗" ++ ++#: Settings.ui.h:33 ++msgid "Use different for unfocused" ++msgstr "為未聚焦視窗使用不同樣式" ++ ++#: Settings.ui.h:34 ++msgid "Font size (px) of the application titles (default is 14)" ++msgstr "應用程式標題字型大小(像素)(預設為 14)" ++ ++#: Settings.ui.h:35 ++msgid "Font weight of application titles" ++msgstr "應用程式標題字型粗細" ++ ++#: Settings.ui.h:36 ++msgid "inherit from theme" ++msgstr "繼承自主題" ++ ++#: Settings.ui.h:37 ++msgid "normal" ++msgstr "normal" ++ ++#: Settings.ui.h:38 ++msgid "lighter" ++msgstr "lighter" ++ ++#: Settings.ui.h:39 ++msgid "bold" ++msgstr "bold" ++ ++#: Settings.ui.h:40 ++msgid "bolder" ++msgstr "bolder" ++ ++#: Settings.ui.h:41 ++msgid "Font color of the application titles" ++msgstr "應用程式標題字型顏色" ++ ++#: Settings.ui.h:42 ++msgid "Maximum width (px) of the application titles (default is 160)" ++msgstr "應用程式標題寬度上限(像素)(預設為 160)" ++ ++#: Settings.ui.h:43 ++msgid "Use a fixed width for the application titles" ++msgstr "為所有應用程式標題使用固定寬度" ++ ++#: Settings.ui.h:44 ++msgid "" ++"The application titles all have the same width, even if their texts are " ++"shorter than the maximum width. The maximum width value is used as the fixed " ++"width." ++msgstr "" ++"所有的應用程式標題共用相同的寬度,即使它們的文字比寬度上限短。寬度上限值被用" ++"作固定寬度。" ++ ++#: Settings.ui.h:45 ++msgid "Display running indicators on unfocused applications" ++msgstr "在未聚焦的應用程式上顯示正在執行的指示器" ++ ++#: Settings.ui.h:46 ++msgid "Use the favorite icons as application launchers" ++msgstr "為應用程式啟動器使用收藏的圖示" ++ ++#: Settings.ui.h:47 ++msgid "Only hide the panel when it is obstructed by windows " ++msgstr "僅在面板被視窗阻擋時才將其隱藏 " ++ ++#: Settings.ui.h:48 ++msgid "The panel hides from" ++msgstr "面板隱藏自" ++ ++#: Settings.ui.h:49 ++msgid "All windows" ++msgstr "所有視窗" ++ ++#: Settings.ui.h:50 ++msgid "Focused windows" ++msgstr "焦點視窗" ++ ++#: Settings.ui.h:51 ++msgid "Maximized windows" ++msgstr "最大化視窗" ++ ++#: Settings.ui.h:52 ++msgid "Require pressure at the edge of the screen to reveal the panel" ++msgstr "在螢幕邊緣受到一定游標壓力時顯示面板" ++ ++#: Settings.ui.h:53 ++msgid "Required pressure threshold (px)" ++msgstr "所需壓力閾值(像素)" ++ ++#: Settings.ui.h:54 ++msgid "Required pressure timeout (ms)" ++msgstr "所需壓力等候時間(毫秒)" ++ ++#: Settings.ui.h:55 ++msgid "Allow the panel to be revealed while in fullscreen mode" ++msgstr "允許在全螢幕模式下顯示面板" ++ ++#: Settings.ui.h:56 ++msgid "Only hide secondary panels (requires multi-monitors option)" ++msgstr "僅隱藏次級面板(需要多顯示器選項)" ++ ++#: Settings.ui.h:57 ++msgid "e.g. i" ++msgstr "例如 i" ++ ++#: Settings.ui.h:58 ++msgid "Keyboard shortcut to reveal and hold the panel" ++msgstr "顯示並保持面板的鍵盤快速鍵" ++ ++#: Settings.ui.h:59 ++msgid "Syntax: , , , " ++msgstr "語法: , , , " ++ ++#: Settings.ui.h:60 ++msgid "Hide and reveal animation duration (ms)" ++msgstr "隱藏及顯示動畫持續時間(毫秒)" ++ ++#: Settings.ui.h:61 ++msgid "Delay before hiding the panel (ms)" ++msgstr "隱藏面板前的延遲(毫秒)" ++ ++#: Settings.ui.h:62 ++msgid "Time (ms) before showing (100 is default)" ++msgstr "顯示前的延遲(毫秒)(預設為 100)" ++ ++#: Settings.ui.h:63 ++msgid "Time (ms) before hiding (100 is default)" ++msgstr "隱藏前的延遲(毫秒)(預設為 100)" ++ ++#: Settings.ui.h:64 ++msgid "Animation time (ms)" ++msgstr "動畫時間(毫秒)" ++ ++#: Settings.ui.h:65 ++msgid "Middle click on the preview to close the window" ++msgstr "在預覽介面點選中鍵以關閉視窗" ++ ++#: Settings.ui.h:66 ++msgid "Window previews preferred size (px)" ++msgstr "視窗預覽慣用大小(像素)" ++ ++#: Settings.ui.h:67 ++msgid "Window previews aspect ratio Y (height)" ++msgstr "視窗預覽外觀比例 Y(高度)" ++ ++#: Settings.ui.h:68 ++msgid "Window previews padding (px)" ++msgstr "視窗預覽間距(像素)" ++ ++#: Settings.ui.h:69 ++msgid "1" ++msgstr "1" ++ ++#: Settings.ui.h:70 ++msgid "2" ++msgstr "2" ++ ++#: Settings.ui.h:71 ++msgid "3" ++msgstr "3" ++ ++#: Settings.ui.h:72 ++msgid "4" ++msgstr "4" ++ ++#: Settings.ui.h:73 ++msgid "5" ++msgstr "5" ++ ++#: Settings.ui.h:74 ++msgid "6" ++msgstr "6" ++ ++#: Settings.ui.h:75 ++msgid "7" ++msgstr "7" ++ ++#: Settings.ui.h:76 ++msgid "8" ++msgstr "8" ++ ++#: Settings.ui.h:77 ++msgid "9" ++msgstr "9" ++ ++#: Settings.ui.h:78 ++msgid "10" ++msgstr "10" ++ ++#: Settings.ui.h:79 ++msgid "11" ++msgstr "11" ++ ++#: Settings.ui.h:80 ++msgid "12" ++msgstr "12" ++ ++#: Settings.ui.h:81 ++msgid "13" ++msgstr "13" ++ ++#: Settings.ui.h:82 ++msgid "14" ++msgstr "14" ++ ++#: Settings.ui.h:83 ++msgid "15" ++msgstr "15" ++ ++#: Settings.ui.h:84 ++msgid "16" ++msgstr "16" ++ ++#: Settings.ui.h:85 ++msgid "17" ++msgstr "17" ++ ++#: Settings.ui.h:86 ++msgid "18" ++msgstr "18" ++ ++#: Settings.ui.h:87 ++msgid "19" ++msgstr "19" ++ ++#: Settings.ui.h:88 ++msgid "20" ++msgstr "20" ++ ++#: Settings.ui.h:89 ++msgid "21" ++msgstr "21" ++ ++#: Settings.ui.h:90 ++msgid "Fixed" ++msgstr "固定" ++ ++#: Settings.ui.h:91 ++msgid "Window previews aspect ratio X (width)" ++msgstr "視窗預覽外觀比例 X(寬度)" ++ ++#: Settings.ui.h:92 ++msgid "Use custom opacity for the previews background" ++msgstr "為預覽介面背景使用自定義不透明度" ++ ++#: Settings.ui.h:93 ++msgid "If disabled, the previews background have the same opacity as the panel" ++msgstr "若停用,則預覽介面背景將與面板使用相同的不透明度" ++ ++#: Settings.ui.h:94 ++msgid "Close button and header position" ++msgstr "關閉按鈕及頁首位置" ++ ++#: Settings.ui.h:95 ++msgid "Bottom" ++msgstr "底部" ++ ++#: Settings.ui.h:96 ++msgid "Top" ++msgstr "頂部" ++ ++#: Settings.ui.h:97 ++msgid "Display window preview headers" ++msgstr "顯示視窗預覽開頭" ++ ++#: Settings.ui.h:98 ++msgid "Font size (px) of the preview titles" ++msgstr "預覽標題字型大小(像素)" ++ ++#: Settings.ui.h:99 ++msgid "Font weight of the preview titles" ++msgstr "預覽標題字型粗細" ++ ++#: Settings.ui.h:100 ++msgid "Font color of the preview titles" ++msgstr "預覽標題字型顏色" ++ ++#: Settings.ui.h:101 ++msgid "Enable window peeking" ++msgstr "啟用視窗查看" ++ ++#: Settings.ui.h:102 ++msgid "" ++"When hovering over a window preview for some time, the window gets " ++"distinguished." ++msgstr "當滑鼠指標在某一視窗預覽介面上懸停一段時間,區分該視窗。" ++ ++#: Settings.ui.h:103 ++msgid "Enter window peeking mode timeout (ms)" ++msgstr "進入視窗查看模式等候時間(毫秒)" ++ ++#: Settings.ui.h:104 ++msgid "50" ++msgstr "50" ++ ++#: Settings.ui.h:105 ++msgid "" ++"Time of inactivity while hovering over a window preview needed to enter the " ++"window peeking mode." ++msgstr "當在某一視窗預覽介面上暫留並進入視窗查看模式所需的時間。" ++ ++#: Settings.ui.h:106 ++msgid "Window peeking mode opacity" ++msgstr "視窗查看模式不透明度" ++ ++#: Settings.ui.h:107 ++msgid "0" ++msgstr "0" ++ ++#: Settings.ui.h:108 ++msgid "" ++"All windows except for the peeked one have their opacity set to the same " ++"value." ++msgstr "除被查看的視窗外,所有視窗的不透明度將被設定為同一值。" ++ ++#: Settings.ui.h:109 ++msgid "Super" ++msgstr "Super" ++ ++#: Settings.ui.h:110 ++msgid "Super + Alt" ++msgstr "Super + Alt" ++ ++#: Settings.ui.h:111 ++msgid "Hotkeys prefix" ++msgstr "快速鍵" ++ ++#: Settings.ui.h:112 ++msgid "Hotkeys will either be Super+Number or Super+Alt+Num" ++msgstr "快速鍵將被設定為 Super+Number 或者 Super+Alt+Num" ++ ++#: Settings.ui.h:113 ++msgid "Never" ++msgstr "永不" ++ ++#: Settings.ui.h:114 ++msgid "Show temporarily" ++msgstr "暫時顯示" ++ ++#: Settings.ui.h:115 ++msgid "Always visible" ++msgstr "永遠顯示" ++ ++#: Settings.ui.h:116 ++msgid "Number overlay" ++msgstr "編號重疊" ++ ++#: Settings.ui.h:117 ++msgid "" ++"Temporarily show the application numbers over the icons when using the " ++"hotkeys." ++msgstr "當使用快速鍵時暫時在應用程式圖示上顯示其編號。" ++ ++#: Settings.ui.h:118 ++msgid "Hide timeout (ms)" ++msgstr "隱藏等候時間(毫秒)" ++ ++#: Settings.ui.h:119 ++msgid "e.g. q" ++msgstr "例如 q" ++ ++#: Settings.ui.h:120 ++msgid "Shortcut to show the overlay for 2 seconds" ++msgstr "顯示 2 秒重疊的快速鍵" ++ ++#: Settings.ui.h:121 ++msgid "Show window previews on hotkey" ++msgstr "使用快速鍵時顯示視窗預覽介面" ++ ++#: Settings.ui.h:122 ++msgid "Show previews when the application have multiple instances" ++msgstr "當應用程式有多個實例時顯示預覽" ++ ++#: Settings.ui.h:123 ++msgid "Current Show Applications icon" ++msgstr "目前的“顯示應用程式”圖示" ++ ++#: Settings.ui.h:124 ++msgid "Select a Show Applications image icon" ++msgstr "選取一個“顯示應用程式”圖示" ++ ++#: Settings.ui.h:125 ++msgid "Custom Show Applications image icon" ++msgstr "自訂“顯示應用程式”圖示圖片" ++ ++#: Settings.ui.h:126 ++msgid "Show Applications icon side padding (px)" ++msgstr "“顯示應用程式”圖示邊框間距" ++ ++#: Settings.ui.h:127 ++msgid "Show Desktop button width (px)" ++msgstr "“顯示桌面”按鈕大小(像素)" ++ ++#: Settings.ui.h:128 ++msgid "Reveal the desktop when hovering the Show Desktop button" ++msgstr "當滑鼠指標在“顯示桌面”按鈕上懸停一段時間則預覽桌面" ++ ++#: Settings.ui.h:129 ++msgid "Delay before revealing the desktop (ms)" ++msgstr "預覽桌面前的延遲(毫秒)" ++ ++#: Settings.ui.h:130 ++msgid "Fade duration (ms)" ++msgstr "淡出效果持續時間(毫秒)" ++ ++#: Settings.ui.h:131 ++msgid "The panel background opacity is affected by" ++msgstr "面板背景不透明度受影響於" ++ ++#: Settings.ui.h:132 ++msgid "Change opacity when a window gets closer than (px)" ++msgstr "當視窗靠近時改變不透明度(像素)" ++ ++#: Settings.ui.h:134 ++#, no-c-format ++msgid "Change opacity to (%)" ++msgstr "改變不透明度為(%)" ++ ++#: Settings.ui.h:135 ++msgid "Opacity change animation duration (ms)" ++msgstr "不透明度變化動畫持續時間(毫秒)" ++ ++#: Settings.ui.h:136 ++msgid "Panel screen position" ++msgstr "面板在螢幕中所處的位置" ++ ++#: Settings.ui.h:137 ++msgid "Taskbar position" ++msgstr "工作列位置" ++ ++#: Settings.ui.h:138 ++msgid "Left, with plugin icons collapsed to right" ++msgstr "左側,並將外掛圖示摺疊到右側" ++ ++#: Settings.ui.h:139 ++msgid "Left, with fixed center plugin icons" ++msgstr "左側,並固定居中外掛圖示" ++ ++#: Settings.ui.h:140 ++msgid "Left, with floating center plugin icons" ++msgstr "左側,並浮動居中外掛圖示" ++ ++#: Settings.ui.h:141 ++msgid "Center, fixed in middle of monitor" ++msgstr "中間,固定於顯示器中間" ++ ++#: Settings.ui.h:142 ++msgid "Center, floating between left and right elements" ++msgstr "中間,在左側及右側元素中浮動" ++ ++#: Settings.ui.h:143 ++msgid "Clock location" ++msgstr "時鐘位置" ++ ++#: Settings.ui.h:144 ++msgid "Left of plugin icons" ++msgstr "外掛圖示左側" ++ ++#: Settings.ui.h:145 ++msgid "Right of plugin icons" ++msgstr "外掛圖示右側" ++ ++#: Settings.ui.h:146 ++msgid "Left of system indicators" ++msgstr "系統指示器左側" ++ ++#: Settings.ui.h:147 ++msgid "Right of system indicators" ++msgstr "系統指示器右側" ++ ++#: Settings.ui.h:148 ++msgid "Left of taskbar" ++msgstr "工作列左側" ++ ++#: Settings.ui.h:149 ++msgid "Right of taskbar" ++msgstr "工作列右側" ++ ++#: Settings.ui.h:150 ++msgid "Display the main panel on" ++msgstr "將主面板顯示於" ++ ++#: Settings.ui.h:151 ++msgid "Display panels on all monitors" ++msgstr "在所有顯示器上顯示面板" ++ ++#: Settings.ui.h:152 ++msgid "Panel Intellihide" ++msgstr "面板智慧隱藏" ++ ++#: Settings.ui.h:153 ++msgid "Hide and reveal the panel according to preferences" ++msgstr "依偏好設定隱藏和顯示面板" ++ ++#: Settings.ui.h:154 ++msgid "Position" ++msgstr "位置" ++ ++#: Settings.ui.h:155 ++msgid "" ++"Panel Size\n" ++"(default is 48)" ++msgstr "" ++"面板大小\n" ++"(預設為 48)" ++ ++#: Settings.ui.h:157 ++msgid "" ++"App Icon Margin\n" ++"(default is 8)" ++msgstr "" ++"應用圖示邊界\n" ++"(預設為 8)" ++ ++#: Settings.ui.h:159 ++msgid "" ++"App Icon Padding\n" ++"(default is 4)" ++msgstr "" ++"應用圖示邊框間距\n" ++"(預設為 4)" ++ ++#: Settings.ui.h:161 ++msgid "Running indicator position" ++msgstr "執行指示器位置" ++ ++#: Settings.ui.h:162 ++msgid "Running indicator style (Focused app)" ++msgstr "執行指示器樣式(焦點應用)" ++ ++#: Settings.ui.h:163 ++msgid "Dots" ++msgstr "點" ++ ++#: Settings.ui.h:164 ++msgid "Squares" ++msgstr "方塊" ++ ++#: Settings.ui.h:165 ++msgid "Dashes" ++msgstr "虛線" ++ ++#: Settings.ui.h:166 ++msgid "Segmented" ++msgstr "分割線" ++ ++#: Settings.ui.h:167 ++msgid "Solid" ++msgstr "實心" ++ ++#: Settings.ui.h:168 ++msgid "Ciliora" ++msgstr "Ciliora" ++ ++#: Settings.ui.h:169 ++msgid "Metro" ++msgstr "Metro" ++ ++#: Settings.ui.h:170 ++msgid "Running indicator style (Unfocused apps)" ++msgstr "執行指示器樣式(未聚焦應用)" ++ ++#: Settings.ui.h:171 ++msgid "Override panel theme background color " ++msgstr "覆寫面板主題背景色 " ++ ++#: Settings.ui.h:172 ++msgid "Override panel theme background opacity" ++msgstr "覆寫面板主題背景不透明度" ++ ++#: Settings.ui.h:174 ++#, no-c-format ++msgid "Panel background opacity (%)" ++msgstr "面板背景不透明度(%)" ++ ++#: Settings.ui.h:175 ++msgid "Dynamic background opacity" ++msgstr "動態背景不透明度" ++ ++#: Settings.ui.h:176 ++msgid "Change opacity when a window gets close to the panel" ++msgstr "在有視窗接近面板時改變不透明度" ++ ++#: Settings.ui.h:177 ++msgid "Override panel theme gradient " ++msgstr "覆寫面板主題漸變 " ++ ++#: Settings.ui.h:179 ++#, no-c-format ++msgid "Gradient top color and opacity (%)" ++msgstr "漸變頂部顏色和不透明度(%)" ++ ++#: Settings.ui.h:181 ++#, no-c-format ++msgid "Gradient bottom color and opacity (%)" ++msgstr "漸變底部顏色和不透明度(%)" ++ ++#: Settings.ui.h:182 ++msgid "Style" ++msgstr "樣式" ++ ++#: Settings.ui.h:183 ++msgid "Show favorite applications" ++msgstr "顯示收藏應用程式" ++ ++#: Settings.ui.h:184 ++msgid "Show running applications" ++msgstr "顯示正在執行的應用程式" ++ ++#: Settings.ui.h:185 ++msgid "Show Applications icon" ++msgstr "顯示應用程式圖示" ++ ++#: Settings.ui.h:186 ++msgid "Animate Show Applications." ++msgstr "動畫化顯示應用程式" ++ ++#: Settings.ui.h:187 ++msgid "Show Activities button" ++msgstr "顯示活動按鈕" ++ ++#: Settings.ui.h:188 ++msgid "Show Desktop button" ++msgstr "顯示桌面按鈕" ++ ++#: Settings.ui.h:189 ++msgid "Show AppMenu button" ++msgstr "顯示應用選單按鈕" ++ ++#: Settings.ui.h:190 ++msgid "Top Bar > Show App Menu must be enabled in Tweak Tool" ++msgstr "必須在調校工具中啟用頂端列 > 應用程式選單" ++ ++#: Settings.ui.h:191 ++msgid "Show window previews on hover" ++msgstr "懸停時顯示視窗預覽" ++ ++#: Settings.ui.h:192 ++msgid "Show tooltip on hover" ++msgstr "懸停時顯示工具提示" ++ ++#: Settings.ui.h:193 ++msgid "Isolate Workspaces" ++msgstr "隔離工作區" ++ ++#: Settings.ui.h:194 ++msgid "Ungroup applications" ++msgstr "取消應用程式分組" ++ ++#: Settings.ui.h:195 ++msgid "Behaviour when clicking on the icon of a running application." ++msgstr "點選正在執行的應用程式圖示時的行為。" ++ ++#: Settings.ui.h:196 ++msgid "Click action" ++msgstr "點選行為" ++ ++#: Settings.ui.h:197 ++msgid "Toggle windows" ++msgstr "切換視窗" ++ ++#: Settings.ui.h:198 ++msgid "" ++"Enable Super+(0-9) as shortcuts to activate apps. It can also be used " ++"together with Shift and Ctrl." ++msgstr "" ++"將 Super+(0-9) 作為啟用應用程式的快速鍵。它也可以和 Shift 及 Ctrl 共同使用。" ++ ++#: Settings.ui.h:199 ++msgid "Use hotkeys to activate apps" ++msgstr "使用熱鍵啟用應用" ++ ++#: Settings.ui.h:200 ++msgid "Behavior" ++msgstr "行為" ++ ++#: Settings.ui.h:201 ++msgid "" ++"Tray Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"工具列字型大小\n" ++"(0 = 主題預設)" ++ ++#: Settings.ui.h:203 ++msgid "" ++"LeftBox Font Size\n" ++"(0 = theme default)" ++msgstr "" ++"LeftBox 字型大小\n" ++"(0 = 主題預設)" ++ ++#: Settings.ui.h:205 ++msgid "" ++"Tray Item Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"工具列項目間距\n" ++"(-1 = 主題預設)" ++ ++#: Settings.ui.h:207 ++msgid "" ++"Status Icon Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"狀態圖示間距\n" ++"(-1 = 主題預設)" ++ ++#: Settings.ui.h:209 ++msgid "" ++"LeftBox Padding\n" ++"(-1 = theme default)" ++msgstr "" ++"LeftBox 間距\n" ++"(-1 = 主題預設)" ++ ++#: Settings.ui.h:211 ++msgid "Animate switching applications" ++msgstr "使切換應用程式時出現動畫" ++ ++#: Settings.ui.h:212 ++msgid "Animate launching new windows" ++msgstr "使啟動新視窗時出現動畫" ++ ++#: Settings.ui.h:213 ++msgid "Keep original gnome-shell dash (overview)" ++msgstr "保留原始 gnome-shell dash(預覽)" ++ ++#: Settings.ui.h:214 ++msgid "Activate panel menu buttons (e.g. date menu) on click only" ++msgstr "僅在點選時啟用面板選單按鈕(例如日期選單)" ++ ++#: Settings.ui.h:215 ++msgid "App icon secondary (right-click) menu" ++msgstr "應用圖示次級(右鍵點選)選單" ++ ++#: Settings.ui.h:217 ++msgid "Fine-Tune" ++msgstr "微調" ++ ++#: Settings.ui.h:218 ++msgid "version: " ++msgstr "版本: " ++ ++#: Settings.ui.h:219 ++msgid "GitHub" ++msgstr "GitHub" ++ ++#: Settings.ui.h:220 ++msgid "" ++"Use the buttons below to create a settings file from your current " ++"preferences that can be imported on a different machine." ++msgstr "" ++"使用下面的按鈕以基於您目前的配置建立一份設定檔;您稍後可使用該檔案在其他機器" ++"上匯入設定。" ++ ++#: Settings.ui.h:221 ++msgid "Export and import settings" ++msgstr "匯入及匯出設定" ++ ++#: Settings.ui.h:222 ++msgid "Export to file" ++msgstr "匯出至檔案" ++ ++#: Settings.ui.h:223 ++msgid "Import from file" ++msgstr "從檔案匯入" ++ ++#: Settings.ui.h:224 ++msgid "" ++"This program comes with ABSOLUTELY NO WARRANTY.\n" ++"See the GNU General Public License, version 2 or later for details." ++msgstr "" ++"本程式不提供任何擔保。\n" ++"請檢視 GNU 通用公共許可證 (GPL),第二版或更新版 以瞭解詳情。" ++ ++#: Settings.ui.h:226 ++msgid "About" ++msgstr "關於" ++ + #~ msgid "CPU" + #~ msgstr "CPU" + +@@ -603,9 +1654,6 @@ msgstr "在桌面顯示垃圾桶圖示。" + #~ msgid "Drag here to add favorites" + #~ msgstr "拖曳至此處以加入喜好" + +-#~ msgid "New Window" +-#~ msgstr "新視窗" +- + #~ msgid "Quit Application" + #~ msgstr "退出應用程式" + +-- +2.38.1 + + +From e8facafa1d16fc62a01c02bcee9e34a388f81572 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 2 Dec 2021 19:39:50 +0100 +Subject: [PATCH 10/11] Add classification-banner + +--- + extensions/classification-banner/extension.js | 170 ++++++++ + extensions/classification-banner/meson.build | 8 + + .../classification-banner/metadata.json.in | 11 + + ...tensions.classification-banner.gschema.xml | 29 ++ + extensions/classification-banner/prefs.js | 363 ++++++++++++++++++ + .../classification-banner/stylesheet.css | 3 + + meson.build | 1 + + 7 files changed, 585 insertions(+) + create mode 100644 extensions/classification-banner/extension.js + create mode 100644 extensions/classification-banner/meson.build + create mode 100644 extensions/classification-banner/metadata.json.in + create mode 100644 extensions/classification-banner/org.gnome.shell.extensions.classification-banner.gschema.xml + create mode 100644 extensions/classification-banner/prefs.js + create mode 100644 extensions/classification-banner/stylesheet.css + +diff --git a/extensions/classification-banner/extension.js b/extensions/classification-banner/extension.js +new file mode 100644 +index 00000000..6c2fe007 +--- /dev/null ++++ b/extensions/classification-banner/extension.js +@@ -0,0 +1,170 @@ ++/* extension.js ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++ ++/* exported init */ ++ ++const { Clutter, Gio, GLib, GObject, St } = imports.gi; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++ ++const ClassificationBanner = GObject.registerClass( ++class ClassificationBanner extends Clutter.Actor { ++ _init(index) { ++ super._init({ ++ layout_manager: new Clutter.BinLayout(), ++ constraints: new Layout.MonitorConstraint({ ++ work_area: true, ++ index, ++ }), ++ }); ++ ++ this._settings = ExtensionUtils.getSettings(); ++ this.connect('destroy', () => { ++ if (this._settings) ++ this._settings.run_dispose(); ++ this._settings = null; ++ }); ++ ++ this._topBanner = new St.BoxLayout({ ++ style_class: 'classification-banner', ++ x_expand: true, ++ y_expand: true, ++ y_align: Clutter.ActorAlign.START, ++ }); ++ this.add_child(this._topBanner); ++ this._settings.bind('top-banner', ++ this._topBanner, 'visible', ++ Gio.SettingsBindFlags.GET); ++ ++ this._bottomBanner = new St.BoxLayout({ ++ style_class: 'classification-banner', ++ x_expand: true, ++ y_expand: true, ++ y_align: Clutter.ActorAlign.END, ++ }); ++ this.add_child(this._bottomBanner); ++ this._settings.bind('bottom-banner', ++ this._bottomBanner, 'visible', ++ Gio.SettingsBindFlags.GET); ++ ++ for (const banner of [this._topBanner, this._bottomBanner]) { ++ const label = new St.Label({ ++ style_class: 'classification-message', ++ x_align: Clutter.ActorAlign.CENTER, ++ x_expand: true, ++ }); ++ banner.add_child(label); ++ ++ this._settings.bind('message', ++ label, 'text', ++ Gio.SettingsBindFlags.GET); ++ } ++ ++ const hostLabel = new St.Label({ ++ style_class: 'classification-system-info', ++ text: GLib.get_host_name(), ++ }); ++ this._topBanner.insert_child_at_index(hostLabel, 0); ++ this._settings.bind('system-info', ++ hostLabel, 'visible', ++ Gio.SettingsBindFlags.GET); ++ ++ const userLabel = new St.Label({ ++ style_class: 'classification-system-info', ++ text: GLib.get_user_name(), ++ }); ++ this._topBanner.add_child(userLabel); ++ this._settings.bind('system-info', ++ userLabel, 'visible', ++ Gio.SettingsBindFlags.GET); ++ ++ this._settings.connect('changed::color', ++ () => this._updateStyles()); ++ this._settings.connect('changed::background-color', ++ () => this._updateStyles()); ++ this._updateStyles(); ++ } ++ ++ _getColorSetting(key) { ++ const str = this._settings.get_string(key); ++ const [valid, color] = Clutter.Color.from_string(str); ++ if (!valid) ++ return ''; ++ const { red, green, blue, alpha } = color; ++ return `${key}: rgba(${red},${green},${blue},${alpha / 255});`; ++ } ++ ++ _updateStyles() { ++ const bgStyle = this._getColorSetting('background-color'); ++ const fgStyle = this._getColorSetting('color'); ++ const style = `${bgStyle}${fgStyle}`; ++ this._topBanner.set({ style }); ++ this._bottomBanner.set({ style }); ++ } ++}); ++ ++class Extension { ++ constructor() { ++ this._banners = []; ++ } ++ ++ _updateMonitors() { ++ const { monitors, panelBox, primaryIndex } = Main.layoutManager; ++ if (monitors.length !== this._banners.length) { ++ this._clearBanners(); ++ ++ for (let i = 0; i < monitors.length; i++) { ++ const banner = new ClassificationBanner(i); ++ Main.uiGroup.add_child(banner); ++ this._banners.push(banner); ++ } ++ } ++ ++ const primaryBanner = this._banners[primaryIndex]; ++ if (primaryBanner) ++ Main.uiGroup.set_child_below_sibling(primaryBanner, panelBox); ++ } ++ ++ _clearBanners() { ++ this._banners.forEach(b => b.destroy()); ++ this._banners = []; ++ } ++ ++ enable() { ++ this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', ++ () => this._updateMonitors()); ++ this._updateMonitors(); ++ } ++ ++ disable() { ++ if (this._monitorsChangedId) { ++ Main.layoutManager.disconnect(this._monitorsChangedId); ++ delete this._monitorsChangedId; ++ } ++ this._clearBanners(); ++ } ++} ++ ++/** ++ * @returns {Extension} - the extension's state object ++ */ ++function init() { ++ return new Extension(); ++} +diff --git a/extensions/classification-banner/meson.build b/extensions/classification-banner/meson.build +new file mode 100644 +index 00000000..c55a7830 +--- /dev/null ++++ b/extensions/classification-banner/meson.build +@@ -0,0 +1,8 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_sources += files('prefs.js') ++extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') +diff --git a/extensions/classification-banner/metadata.json.in b/extensions/classification-banner/metadata.json.in +new file mode 100644 +index 00000000..1ec884f8 +--- /dev/null ++++ b/extensions/classification-banner/metadata.json.in +@@ -0,0 +1,11 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Classification Banner", ++"description": "Display classification level banner", ++"shell-version": [ "@shell_current@" ], ++"session-modes": [ "gdm", "lock-screen", "unlock-dialog", "user" ], ++"url": "@url@" ++} +diff --git a/extensions/classification-banner/org.gnome.shell.extensions.classification-banner.gschema.xml b/extensions/classification-banner/org.gnome.shell.extensions.classification-banner.gschema.xml +new file mode 100644 +index 00000000..0314ef60 +--- /dev/null ++++ b/extensions/classification-banner/org.gnome.shell.extensions.classification-banner.gschema.xml +@@ -0,0 +1,29 @@ ++ ++ ++ ++ true ++ Show a banner at the top ++ ++ ++ true ++ Show a banner at the bottom ++ ++ ++ "UNCLASSIFIED" ++ classification message ++ ++ ++ "#fff" ++ text color ++ ++ ++ "rgba(0,122,51,0.75)" ++ background color ++ ++ ++ false ++ Include system info in top banner ++ ++ ++ +diff --git a/extensions/classification-banner/prefs.js b/extensions/classification-banner/prefs.js +new file mode 100644 +index 00000000..607d4002 +--- /dev/null ++++ b/extensions/classification-banner/prefs.js +@@ -0,0 +1,363 @@ ++/* exported init buildPrefsWidget */ ++const { Gdk, Gio, GObject, Gtk } = imports.gi; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++ ++let settings = null; ++ ++var PreferencesGroup = GObject.registerClass( ++class PreferencesGroup extends Gtk.ListBox { ++ _init(params) { ++ super._init({ ++ ...params, ++ selection_mode: Gtk.SelectionMode.NONE, ++ }); ++ ++ const styleContext = this.get_style_context(); ++ styleContext.add_class('frame'); ++ styleContext.add_class('rich-list'); ++ ++ this.set_header_func(this._updateHeader.bind(this)); ++ this.connect('row-activated', ++ (box, row) => row.activate()); ++ } ++ ++ _updateHeader(row, before) { ++ if (!before || row.get_header()) ++ return; ++ row.set_header(new Gtk.Separator()); ++ } ++}); ++ ++ ++var ActionRow = GObject.registerClass({ ++ Properties: { ++ 'activatable-widget': GObject.ParamSpec.object( ++ 'activatable-widget', 'activatable-widget', 'activatable-widget', ++ GObject.ParamFlags.READWRITE, ++ Gtk.Widget), ++ 'title': GObject.ParamSpec.string( ++ 'title', 'title', 'title', ++ GObject.ParamFlags.READWRITE, ++ null), ++ }, ++}, class ActionRow extends Gtk.ListBoxRow { ++ _init(params) { ++ super._init(params); ++ ++ const box = new Gtk.Box({ ++ valign: Gtk.Align.CENTER, ++ spacing: 12, ++ margin_top: 8, ++ margin_bottom: 8, ++ margin_start: 12, ++ margin_end: 12, ++ }); ++ this.add(box); ++ ++ const provider = new Gtk.CssProvider(); ++ provider.load_from_data('* { min-height: 32px; }'); ++ box.get_style_context().add_provider(provider, ++ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); ++ ++ this._prefixes = new Gtk.Box({ ++ spacing: 12, ++ no_show_all: true, ++ visible: false, ++ }); ++ box.add(this._prefixes); ++ ++ this._title = new Gtk.Label({ ++ hexpand: true, ++ xalign: 0, ++ }); ++ this._title.get_style_context().add_class('title'); ++ box.add(this._title); ++ ++ this._suffixes = new Gtk.Box({ ++ spacing: 12, ++ no_show_all: true, ++ visible: false, ++ }); ++ box.add(this._suffixes); ++ ++ this.bind_property('title', ++ this._title, 'label', ++ GObject.BindingFlags.SYNC_CREATE); ++ } ++ ++ activate() { ++ if (this.activatable_widget) ++ this.activatable_widget.mnemonic_activate(false); ++ } ++ ++ add_prefix(child) { ++ child.show(); ++ this._prefixes.add(child); ++ this._prefixes.show(); ++ } ++ ++ add_suffix(child) { ++ child.show(); ++ this._suffixes.add(child); ++ this._suffixes.show(); ++ } ++}); ++ ++var ComboRow = GObject.registerClass({ ++ Properties: { ++ 'selected-item': GObject.ParamSpec.object( ++ 'selected-item', 'selected-item', 'selected-item', ++ GObject.ParamFlags.READABLE, ++ GObject.Object), ++ }, ++}, class ComboRow extends ActionRow { ++ _init(params) { ++ super._init({ ++ ...params, ++ activatable: true, ++ }); ++ ++ const box = new Gtk.Box({ ++ valign: Gtk.Align.CENTER, ++ }); ++ box.add(new Gtk.Image({ ++ icon_name: 'pan-down-symbolic', ++ visible: true, ++ })); ++ this.add_suffix(box); ++ ++ this._popover = new Gtk.Popover({ ++ relative_to: box, ++ }); ++ ++ this._listBox = new Gtk.ListBox({ ++ activate_on_single_click: true, ++ selection_mode: Gtk.SelectionMode.SINGLE, ++ visible: true, ++ }); ++ this._popover.add(this._listBox); ++ ++ this._listBox.connect('row-activated', (view, row) => { ++ this._selectedItem = row; ++ this.notify('selected-item'); ++ this._popover.popdown(); ++ }); ++ } ++ ++ get selected_item() { ++ return this._selectedItem; ++ } ++ ++ add_row(row) { ++ row.show(); ++ this._listBox.add(row); ++ } ++ ++ activate() { ++ this._popover.popup(); ++ } ++}); ++ ++const GenericPrefs = GObject.registerClass( ++class GenericPrefs extends PreferencesGroup { ++ _init() { ++ super._init(); ++ ++ this._actionGroup = new Gio.SimpleActionGroup(); ++ this.insert_action_group('options', this._actionGroup); ++ ++ this._actionGroup.add_action(settings.create_action('top-banner')); ++ this._actionGroup.add_action(settings.create_action('bottom-banner')); ++ this._actionGroup.add_action(settings.create_action('system-info')); ++ ++ this.add(this._createSettingsRow('Top banner', 'top-banner')); ++ this.add(this._createSettingsRow('Bottom banner', 'bottom-banner')); ++ this.add(this._createSettingsRow('System info', 'system-info')); ++ } ++ ++ _createSettingsRow(title, key) { ++ const activatableWidget = new Gtk.Switch({ ++ valign: Gtk.Align.CENTER, ++ action_name: `options.${key}`, ++ }); ++ const row = new ActionRow({ ++ activatableWidget, ++ title, ++ }); ++ row.add_prefix(activatableWidget); ++ ++ return row; ++ } ++}); ++ ++const BannerPreset = GObject.registerClass({ ++ Properties: { ++ 'message': GObject.ParamSpec.string( ++ 'message', 'message', 'message', ++ GObject.ParamFlags.READWRITE, ++ null), ++ 'color': GObject.ParamSpec.string( ++ 'color', 'color', 'color', ++ GObject.ParamFlags.READWRITE, ++ null), ++ 'background-color': GObject.ParamSpec.string( ++ 'background-color', 'background-color', 'background-color', ++ GObject.ParamFlags.READWRITE, ++ null), ++ }, ++}, class BannerPreset extends Gtk.ListBoxRow { ++ _init(params) { ++ super._init(params); ++ ++ const label = new Gtk.Label({ ++ label: this.message, ++ visible: true, ++ }); ++ this.add(label); ++ ++ const provider = new Gtk.CssProvider(); ++ provider.load_from_data(`* { ++ border-radius: 99px; ++ padding: 6px; ++ color: ${this.color}; ++ background-color: ${this.background_color}; ++ }`); ++ label.get_style_context().add_provider(provider, ++ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); ++ } ++}); ++ ++const AppearancePrefs = GObject.registerClass( ++class AppearancePrefs extends PreferencesGroup { ++ _init() { ++ super._init(); ++ ++ let row, activatableWidget; ++ row = new ComboRow({ ++ title: _('Presets'), ++ }); ++ row.add_row(new BannerPreset({ ++ message: 'UNCLASSIFIED', ++ color: '#fff', ++ background_color: 'rgba(0, 122, 51, 0.75)', ++ })); ++ row.add_row(new BannerPreset({ ++ message: 'CONFIDENTIAL', ++ color: '#fff', ++ background_color: 'rgba(0, 51, 160, 0.75)', ++ })); ++ row.add_row(new BannerPreset({ ++ message: 'SECRET', ++ color: '#fff', ++ background_color: 'rgba(200, 16, 46, 0.75)', ++ })); ++ row.add_row(new BannerPreset({ ++ message: 'TOP SECRET', ++ color: '#fff', ++ background_color: 'rgba(255, 103, 31, 0.75)', ++ })); ++ row.add_row(new BannerPreset({ ++ message: 'TOP SECRET//SCI', ++ color: '#000', ++ background_color: 'rgba(247, 234, 72, 0.75)', ++ })); ++ ++ row.connect('notify::selected-item', comboRow => { ++ const { message, color, background_color: backgroundColor } = ++ comboRow.selected_item; ++ settings.set_string('message', message); ++ settings.set_string('color', color); ++ settings.set_string('background-color', backgroundColor); ++ }); ++ this.add(row); ++ ++ activatableWidget = new Gtk.Entry({ ++ valign: Gtk.Align.CENTER, ++ }); ++ settings.bind('message', ++ activatableWidget, 'text', ++ Gio.SettingsBindFlags.DEFAULT); ++ row = new ActionRow({ title: _('Message'), activatableWidget }); ++ row.add_suffix(activatableWidget); ++ this.add(row); ++ ++ activatableWidget = this._createColorButton('background-color', { ++ use_alpha: true, ++ }); ++ row = new ActionRow({ title: _('Background color'), activatableWidget }); ++ row.add_suffix(activatableWidget); ++ this.add(row); ++ ++ activatableWidget = this._createColorButton('color'); ++ row = new ActionRow({ title: _('Text color'), activatableWidget }); ++ row.add_suffix(activatableWidget); ++ this.add(row); ++ } ++ ++ _createColorButton(key, params = {}) { ++ const rgba = new Gdk.RGBA(); ++ rgba.parse(settings.get_string(key)); ++ ++ const button = new Gtk.ColorButton({ ++ ...params, ++ rgba, ++ valign: Gtk.Align.CENTER, ++ }); ++ settings.connect(`changed::${key}`, () => { ++ const newRgba = new Gdk.RGBA(); ++ newRgba.parse(settings.get_string(key)); ++ if (!newRgba.equal(button.rgba)) ++ button.set({ rgba: newRgba }); ++ }); ++ button.connect('notify::rgba', ++ () => settings.set_string(key, button.rgba.to_string())); ++ return button; ++ } ++}); ++ ++const ClassificationPrefs = GObject.registerClass( ++class ClassificationPrefs extends Gtk.ScrolledWindow { ++ _init() { ++ super._init({ ++ hscrollbar_policy: Gtk.PolicyType.NEVER, ++ }); ++ ++ const box = new Gtk.Box({ ++ orientation: Gtk.Orientation.VERTICAL, ++ halign: Gtk.Align.CENTER, ++ visible: true, ++ spacing: 24, ++ margin_top: 24, ++ margin_bottom: 24, ++ margin_start: 12, ++ margin_end: 12, ++ }); ++ this.add(box); ++ ++ const provider = new Gtk.CssProvider(); ++ provider.load_from_data('* { min-width: 500px; }'); ++ box.get_style_context().add_provider(provider, ++ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); ++ ++ box.add(new AppearancePrefs()); ++ box.add(new GenericPrefs()); ++ ++ this.show_all(); ++ } ++}); ++ ++/** */ ++function init() { ++ ExtensionUtils.initTranslations(); ++ settings = ExtensionUtils.getSettings(); ++} ++ ++/** ++ * @returns {Gtk.Widget} - the prefs widget ++ */ ++function buildPrefsWidget() { ++ return new ClassificationPrefs(); ++} +diff --git a/extensions/classification-banner/stylesheet.css b/extensions/classification-banner/stylesheet.css +new file mode 100644 +index 00000000..fb6a697e +--- /dev/null ++++ b/extensions/classification-banner/stylesheet.css +@@ -0,0 +1,3 @@ ++.classification-system-info { padding: 0 24px; } ++.classification-message { font-weight: bold; } ++.classification-banner { font-size: 0.9em; } +diff --git a/meson.build b/meson.build +index d4791263..75a2beaa 100644 +--- a/meson.build ++++ b/meson.build +@@ -50,6 +50,7 @@ default_extensions += [ + all_extensions = default_extensions + all_extensions += [ + 'auto-move-windows', ++ 'classification-banner', + 'dash-to-dock', + 'dash-to-panel', + 'disable-screenshield', +-- +2.38.1 + + +From 214b5c2959ab3c0ab64d32b79fbff011302d1af8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 12 Jan 2023 19:43:52 +0100 +Subject: [PATCH 11/11] Add custom-menu extension + +--- + extensions/custom-menu/config.js | 484 ++++++++++++++++++++++++ + extensions/custom-menu/extension.js | 217 +++++++++++ + extensions/custom-menu/meson.build | 7 + + extensions/custom-menu/metadata.json.in | 10 + + extensions/custom-menu/stylesheet.css | 1 + + meson.build | 1 + + 6 files changed, 720 insertions(+) + create mode 100644 extensions/custom-menu/config.js + create mode 100644 extensions/custom-menu/extension.js + create mode 100644 extensions/custom-menu/meson.build + create mode 100644 extensions/custom-menu/metadata.json.in + create mode 100644 extensions/custom-menu/stylesheet.css + +diff --git a/extensions/custom-menu/config.js b/extensions/custom-menu/config.js +new file mode 100644 +index 00000000..652c0223 +--- /dev/null ++++ b/extensions/custom-menu/config.js +@@ -0,0 +1,484 @@ ++const Gio = imports.gi.Gio; ++const GLib = imports.gi.GLib; ++const Json = imports.gi.Json; ++const Lang = imports.lang; ++const Main = imports.ui.main; ++const PopupMenu = imports.ui.popupMenu; ++const ByteArray = imports.byteArray; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const getLogger = Me.imports.extension.getLogger; ++ ++const Entry = new Lang.Class({ ++ Name: 'Entry', ++ Abstract: true, ++ ++ _init: function(prop) { ++ this.type = prop.type; ++ this.title = prop.title || ""; ++ ++ this.__vars = prop.__vars || []; ++ this.updateEnv(prop); ++ }, ++ ++ setTitle: function(text) { ++ this.item.label.get_clutter_text().set_text(text); ++ }, ++ ++ updateEnv: function(prop) { ++ this.__env = {} ++ if(!this.__vars) return; ++ ++ for(let i in this.__vars) { ++ let v = this.__vars[i]; ++ this.__env[v] = prop[v] ? String(prop[v]) : ""; ++ } ++ }, ++ ++ // the pulse function should be read as "a pulse arrives" ++ pulse: function() { }, ++ ++ _try_destroy: function() { ++ try { ++ if(this.item && this.item.destroy) ++ this.item.destroy(); ++ } catch(e) { /* Ignore all errors during destory*/ } ++ }, ++}); ++ ++const DerivedEntry = new Lang.Class({ ++ Name: 'DerivedEntry', ++ ++ _init: function(prop) { ++ if(!prop.base) ++ throw new Error("Base entry not specified in type definition."); ++ ++ this.base = prop.base; ++ this.vars = prop.vars || []; ++ ++ delete prop.base; ++ delete prop.vars; ++ ++ this.prop = prop; ++ }, ++ ++ createInstance: function(addit_prop) { ++ let cls = type_map[this.base]; ++ if(!cls) throw new Error("Bad base class."); ++ if(cls.createInstance) throw new Error("Not allowed to derive from dervied types"); ++ ++ for(let rp in this.prop) ++ addit_prop[rp] = this.prop[rp]; ++ addit_prop.__vars = this.vars; ++ ++ let instance = new cls(addit_prop); ++ ++ return instance; ++ }, ++}); ++ ++/* ++ * callback: function (stdout, stderr, exit_status) { } ++ */ ++let __pipeOpenQueue = []; ++let __pipeExecTimer = null; ++ ++function pipeOpen(cmdline, env, callback) { ++ let param = [cmdline, env, callback] ++ __pipeOpenQueue.push(param); ++ if(__pipeExecTimer === null) { ++ __pipeExecTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 50, ++ function() { ++ let param = __pipeOpenQueue.shift(); ++ if(param === undefined) { ++ __pipeExecTimer = null; ++ return false; ++ } ++ if(realPipeOpen) realPipeOpen(param[0], param[1], param[2]); ++ return true; ++ }); ++ ++ } ++} ++ ++function realPipeOpen(cmdline, env, callback) { ++ let user_cb = callback; ++ let proc; ++ ++ function wait_cb(_, _res) { ++ let stdout_pipe = proc.get_stdout_pipe(); ++ let stderr_pipe = proc.get_stderr_pipe(); ++ ++ let stdout_content; ++ let stderr_content; ++ ++ // Only the first GLib.MAXINT16 characters are fetched for optimization. ++ stdout_pipe.read_bytes_async(GLib.MAXINT16, 0, null, function(osrc, ores) { ++ stdout_content = ByteArray.toString(stdout_pipe.read_bytes_finish(ores).get_data()); ++ stdout_pipe.close(null); ++ ++ stderr_pipe.read_bytes_async(GLib.MAXINT16, 0, null, function(esrc, eres) { ++ stderr_content = ByteArray.toString(stderr_pipe.read_bytes_finish(eres).get_data()); ++ stderr_pipe.close(null); ++ ++ user_cb(stdout_content, stderr_content, proc.get_exit_status()); ++ }); ++ }); ++ } ++ ++ if(user_cb) { ++ let _pipedLauncher = new Gio.SubprocessLauncher({ ++ flags: ++ Gio.SubprocessFlags.STDERR_PIPE | ++ Gio.SubprocessFlags.STDOUT_PIPE ++ }); ++ for(let key in env) { ++ _pipedLauncher.setenv(key, env[key], true); ++ } ++ proc = _pipedLauncher.spawnv(['bash', '-c', cmdline]); ++ proc.wait_async(null, wait_cb); ++ } else { ++ // Detached launcher is used to spawn commands that we are not concerned ++ // about its result. ++ let _detacLauncher = new Gio.SubprocessLauncher(); ++ for(let key in env) { ++ _detacLauncher.setenv(key, env[key], true); ++ } ++ proc = _detacLauncher.spawnv(['bash', '-c', cmdline]); ++ } ++ ++ getLogger().info("Spawned " + cmdline); ++ ++ // log(`Spawning ${cmdline}`); TODO: BEN ++ return proc.get_identifier(); ++} ++ ++function _generalSpawn(command, env, title) { ++ title = title || "Process"; ++ pipeOpen(command, env, function(stdout, stderr, exit_status) { ++ if(exit_status != 0) { ++ log ++ getLogger().warning(stderr); ++ getLogger().notify("proc", title + ++ " exited with status " + exit_status, stderr); ++ } ++ }); ++} ++ ++function quoteShellArg(arg) { ++ arg = arg.replace(/'/g, "'\"'\"'"); ++ return "'" + arg + "'"; ++} ++ ++// This cache is used to reduce detector cost. Each time creating an item, it ++// check if the result of this detector is cached, which prevent the togglers ++// from running detector on each creation. This is useful especially in search ++// mode. ++let _toggler_state_cache = { }; ++ ++const TogglerEntry = new Lang.Class({ ++ Name: 'TogglerEntry', ++ Extends: Entry, ++ ++ _init: function(prop) { ++ this.parent(prop); ++ ++ this.command_on = prop.command_on || ""; ++ this.command_off = prop.command_off || ""; ++ this.detector = prop.detector || ""; ++ this.auto_on = prop.auto_on || false; ++ this.notify_when = prop.notify_when || []; ++ // if the switch is manually turned off, auto_on is disabled. ++ this._manually_switched_off = false; ++ this.pulse(); // load initial state ++ }, ++ ++ createItem: function() { ++ this._try_destroy(); ++ this.item = new PopupMenu.PopupSwitchMenuItem(this.title, false); ++ this.item.label.get_clutter_text().set_use_markup(true); ++ this.item.connect('toggled', Lang.bind(this, this._onManuallyToggled)); ++ this._loadState(); ++ return this.item; ++ }, ++ ++ _onManuallyToggled: function(_, state) { ++ // when switched on again, this flag will get cleared. ++ this._manually_switched_off = !state; ++ this._storeState(state); ++ this._onToggled(state); ++ }, ++ ++ _onToggled: function(state) { ++ if(state) ++ _generalSpawn(this.command_on, this.__env, this.title); ++ else ++ _generalSpawn(this.command_off, this.__env, this.title); ++ }, ++ ++ _detect: function(callback) { ++ // abort detecting if detector is an empty string ++ if(!this.detector) ++ return; ++ ++ pipeOpen(this.detector, this.__env, function(out) { ++ out = String(out); ++ callback(!Boolean(out.match(/^\s*$/))); ++ }); ++ }, ++ ++ compareState: function(new_state) { ++ // compare the new state with cached state ++ // notify when state is different ++ let old_state = _toggler_state_cache[this.detector]; ++ if(old_state === undefined) return; ++ if(old_state == new_state) return; ++ ++ if(this.notify_when.indexOf(new_state ? "on" : "off") >= 0) { ++ let not_str = this.title + (new_state ? " started." : " stopped."); ++ if(!new_state && this.auto_on) ++ not_str += " Attempt to restart it now."; ++ getLogger().notify("state", not_str); ++ } ++ }, ++ ++ _storeState: function(state) { ++ let hash = JSON.stringify({ env: this.__env, detector: this.detector }); ++ _toggler_state_cache[hash] = state; ++ }, ++ ++ _loadState: function() { ++ let hash = JSON.stringify({ env: this.__env, detector: this.detector }); ++ let state = _toggler_state_cache[hash]; ++ if(state !== undefined) ++ this.item.setToggleState(state); // doesn't emit 'toggled' ++ }, ++ ++ pulse: function() { ++ this._detect(Lang.bind(this, function(state) { ++ this.compareState(state); ++ ++ this._storeState(state); ++ this._loadState(); ++ //global.log(this.title + ': ' + this._manually_switched_off); ++ ++ if(!state && !this._manually_switched_off && this.auto_on) ++ // do not call setToggleState here, because command_on may fail ++ this._onToggled(this.item, true); ++ })); ++ }, ++ ++ perform: function() { ++ this.item.toggle(); ++ }, ++}); ++ ++const LauncherEntry = new Lang.Class({ ++ Name: 'LauncherEntry', ++ Extends: Entry, ++ ++ _init: function(prop) { ++ this.parent(prop); ++ ++ this.command = prop.command || ""; ++ }, ++ ++ createItem: function() { ++ this._try_destroy(); ++ ++ this.item = new PopupMenu.PopupMenuItem(this.title); ++ this.item.label.get_clutter_text().set_use_markup(true); ++ this.item.connect('activate', Lang.bind(this, this._onClicked)); ++ ++ return this.item; ++ }, ++ ++ _onClicked: function(_) { ++ _generalSpawn(this.command, this.__env, this.title); ++ }, ++ ++ perform: function() { ++ this.item.emit('activate'); ++ }, ++}); ++ ++const SubMenuEntry = new Lang.Class({ ++ Name: 'SubMenuEntry', ++ Extends: Entry, ++ ++ _init: function(prop) { ++ this.parent(prop) ++ ++ if(prop.entries == undefined) ++ throw new Error("Expected entries provided in submenu entry."); ++ ++ this.entries = []; ++ ++ for(let i in prop.entries) { ++ let entry_prop = prop.entries[i]; ++ let entry = createEntry(entry_prop); ++ this.entries.push(entry); ++ } ++ }, ++ ++ createItem: function() { ++ this._try_destroy(); ++ ++ this.item = new PopupMenu.PopupSubMenuMenuItem(this.title); ++ this.item.label.get_clutter_text().set_use_markup(true); ++ for(let i in this.entries) { ++ let entry = this.entries[i]; ++ this.item.menu.addMenuItem(entry.createItem()); ++ } ++ ++ return this.item; ++ }, ++ ++ pulse: function() { ++ for(let i in this.entries) { ++ let entry = this.entries[i]; ++ entry.pulse(); ++ } ++ } ++}); ++ ++const SeparatorEntry = new Lang.Class({ ++ Name: 'SeparatorEntry', ++ Extends: Entry, ++ ++ _init: function(prop) { }, ++ ++ createItem: function() { ++ this._try_destroy(); ++ ++ this.item = new PopupMenu.PopupSeparatorMenuItem(this.title); ++ this.item.label.get_clutter_text().set_use_markup(true); ++ ++ return this.item; ++ }, ++}); ++ ++let type_map = {}; ++ ++//////////////////////////////////////////////////////////////////////////////// ++// Config Loader loads config from JSON file. ++ ++// convert Json Nodes (GLib based) to native javascript value. ++function convertJson(node) { ++ if(node.get_node_type() == Json.NodeType.VALUE) ++ return node.get_value(); ++ if(node.get_node_type() == Json.NodeType.OBJECT) { ++ let obj = {} ++ node.get_object().foreach_member(function(_, k, v_n) { ++ obj[k] = convertJson(v_n); ++ }); ++ return obj; ++ } ++ if(node.get_node_type() == Json.NodeType.ARRAY) { ++ let arr = [] ++ node.get_array().foreach_element(function(_, i, elem) { ++ arr.push(convertJson(elem)); ++ }); ++ return arr; ++ } ++ return null; ++} ++ ++// ++function createEntry(entry_prop) { ++ if(!entry_prop.type) ++ throw new Error("No type specified in entry."); ++ ++ let cls = type_map[entry_prop.type]; ++ if(!cls) ++ throw new Error("Incorrect type '" + entry_prop.type + "'"); ++ else if(cls.createInstance) ++ return cls.createInstance(entry_prop); ++ ++ return new cls(entry_prop); ++} ++ ++var Loader = new Lang.Class({ ++ Name: 'ConfigLoader', ++ ++ _init: function(filename) { ++ if(filename) ++ this.loadConfig(filename); ++ }, ++ ++ loadConfig: function(filename) { ++ // reset type_map everytime load the config ++ type_map = { ++ launcher: LauncherEntry, ++ toggler: TogglerEntry, ++ submenu: SubMenuEntry, ++ separator: SeparatorEntry ++ }; ++ ++ type_map.systemd = new DerivedEntry({ ++ base: 'toggler', ++ vars: ['unit'], ++ command_on: "pkexec systemctl start ${unit}", ++ command_off: "pkexec systemctl stop ${unit}", ++ detector: "systemctl status ${unit} | grep Active:\\\\s\\*activ[ei]", ++ }); ++ ++ type_map.tmux = new DerivedEntry({ ++ base: 'toggler', ++ vars: ['command', 'session'], ++ command_on: 'tmux new -d -s ${session} bash -c "${command}"', ++ command_off: 'tmux kill-session -t ${session}', ++ detector: 'tmux has -t "${session}" 2>/dev/null && echo yes', ++ }); ++ ++ /* ++ * Refer to README file for detailed config file format. ++ */ ++ this.entries = []; // CAUTION: remove all entries. ++ ++ let config_parser = new Json.Parser(); ++ config_parser.load_from_file(filename); ++ ++ let conf = convertJson(config_parser.get_root()); ++ if (conf.entries == undefined) ++ throw new Error("Key 'entries' not found."); ++ if (conf.deftype) { ++ for (let tname in conf.deftype) { ++ if (type_map[tname]) ++ throw new Error("Type \""+tname+"\" duplicated."); ++ type_map[tname] = new DerivedEntry(conf.deftype[tname]); ++ } ++ } ++ ++ for (let conf_i in conf.entries) { ++ let entry_prop = conf.entries[conf_i]; ++ this.entries.push(createEntry(entry_prop)); ++ } ++ }, ++ ++ ++ saveDefaultConfig: function(filename) { ++ // Write default config ++ const PERMISSIONS_MODE = 0o640; ++ const jsonString = JSON.stringify({ ++ "_homepage_": "https://github.com/andreabenini/gnome-plugin.custom-menu-panel", ++ "_examples_": "https://github.com/andreabenini/gnome-plugin.custom-menu-panel/tree/main/examples", ++ "entries": [ { ++ "type": "launcher", ++ "title": "Edit menu", ++ "command": "gedit $HOME/.entries.json" ++ } ] ++ }, null, 4); ++ let fileConfig = Gio.File.new_for_path(filename); ++ if (GLib.mkdir_with_parents(fileConfig.get_parent().get_path(), PERMISSIONS_MODE) === 0) { ++ fileConfig.replace_contents(jsonString, null, false, Gio.FileCreateFlags.REPLACE_DESTINATION, null); ++ } ++ // Try to load newly saved file ++ try { ++ this.loadConfig(filename); ++ } catch(e) { ++ Main.notify(_('Cannot create and load file: '+filename)); ++ } ++ }, /**/ ++ ++}); +diff --git a/extensions/custom-menu/extension.js b/extensions/custom-menu/extension.js +new file mode 100644 +index 00000000..9f3e3ce8 +--- /dev/null ++++ b/extensions/custom-menu/extension.js +@@ -0,0 +1,217 @@ ++/* extension.js ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++ ++/** ++ * @author Ben ++ * @see https://github.com/andreabenini/gnome-plugin.custom-menu-panel ++ */ ++ ++/* exported init */ ++ ++const GETTEXT_DOMAIN = 'custom-menu-panel'; ++const CONFIGURATION_FILE = '/.entries.json'; ++ ++const { GObject, St } = imports.gi; ++ ++const Gettext = imports.gettext.domain(GETTEXT_DOMAIN); ++const _ = Gettext.gettext; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Lang = imports.lang; ++const GLib = imports.gi.GLib; ++const Gio = imports.gi.Gio; ++const BackgroundMenu = imports.ui.backgroundMenu; ++const Main = imports.ui.main; ++const PanelMenu = imports.ui.panelMenu; ++const PopupMenu = imports.ui.popupMenu; ++ ++const Me = imports.misc.extensionUtils.getCurrentExtension(); ++const Config = Me.imports.config ++ ++const LOGGER_INFO = 0; ++const LOGGER_WARNING = 1; ++const LOGGER_ERROR = 2; ++ ++const { BackgroundMenu: OriginalBackgroundMenu } = BackgroundMenu; ++ ++ ++class CustomMenu extends PopupMenu.PopupMenu { ++ constructor(sourceActor) { ++ super(sourceActor, 0.0, St.Side.TOP, 0); ++ ++ this._loadSetup(); ++ } ++ ++ /** ++ * LOAD Program settings from .entries.json file ++ */ ++ _loadSetup() { ++ this.removeAll(); ++ // Loading configuration from file ++ this.configLoader = new Config.Loader(); ++ try { ++ this.configLoader.loadConfig(GLib.get_home_dir() + CONFIGURATION_FILE); // $HOME/.entries.json ++ } catch(e) { ++ this.configLoader.saveDefaultConfig(GLib.get_home_dir() + CONFIGURATION_FILE); // create default entries ++ } ++ // Build the menu ++ let i = 0; ++ for (let i in this.configLoader.entries) { ++ let item = this.configLoader.entries[i].createItem(); ++ this.addMenuItem(item); ++ } ++ } /**/ ++} ++ ++class CustomBackgroundMenu extends CustomMenu { ++ constructor(layoutManager) { ++ super(layoutManager.dummyCursor); ++ ++ this.actor.add_style_class_name('background-menu'); ++ ++ layoutManager.uiGroup.add_actor(this.actor); ++ this.actor.hide(); ++ ++ this.connect('open-state-changed', (menu, open) => { ++ if (open) ++ this._updateMaxHeight(); ++ }); ++ } ++ ++ _updateMaxHeight() { ++ const monitor = Main.layoutManager.findMonitorForActor(this.actor); ++ const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index); ++ const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage); ++ const vMargins = this.actor.margin_top + this.actor.margin_bottom; ++ const {y: offsetY} = this.sourceActor; ++ ++ const maxHeight = Math.round((monitor.height - offsetY - vMargins) / scaleFactor); ++ this.actor.style = `max-height: ${maxHeight}px;`; ++ } ++} ++ ++const Indicator = GObject.registerClass( ++ class Indicator extends PanelMenu.Button { ++ _init() { ++ super._init(0.0, _('Custom Menu Panel Indicator'), true); ++ this.add_child(new St.Icon({ ++ icon_name: 'view-list-bullet-symbolic', ++ style_class: 'system-status-icon', ++ })); ++ ++ this.setMenu(new CustomMenu(this)); ++ } ++ } ++); ++ ++ ++const Logger = new Lang.Class({ ++ Name: 'Logger', ++ ++ _init: function(log_file) { ++ this._log_file = log_file; ++ // initailize log_backend ++ if(!log_file) ++ this._initEmptyLog(); ++ else if(log_file == "gnome-shell") ++ this._initGnomeLog(); ++ else ++ this._initFileLog(); ++ ++ this.level = LOGGER_WARNING; ++ ++ this.info = function(t) { ++ if(this.level <= LOGGER_INFO) this.log(t) ++ }; ++ this.warning = function(t) { ++ if(this.level <= LOGGER_WARNING) this.log(t) ++ }; ++ this.error = function(t) { ++ if(this.level <= LOGGER_ERROR) this.log(t); ++ }; ++ }, ++ ++ _initEmptyLog: function() { ++ this.log = function(_) { }; ++ }, ++ ++ _initGnomeLog: function() { ++ this.log = function(s) { ++ global.log("custom-menu-panel> " + s); ++ }; ++ }, ++ ++ _initFileLog: function() { ++ this.log = function(s) { ++ // all operations are synchronous: any needs to optimize? ++ if(!this._output_file || !this._output_file.query_exists(null) || ++ !this._fstream || this._fstream.is_closed()) { ++ ++ this._output_file = Gio.File.new_for_path(this._log_file); ++ this._fstream = this._output_file.append_to( ++ Gio.FileCreateFlags.NONE, null); ++ ++ if(!this._fstream instanceof Gio.FileIOStream) { ++ this._initGnomeLog(); ++ this.log("IOError: Failed to append to " + this._log_file + ++ " [Gio.IOErrorEnum:" + this._fstream + "]"); ++ return; ++ } ++ } ++ ++ this._fstream.write(String(new Date())+" "+s+"\n", null); ++ this._fstream.flush(null); ++ } ++ }, ++ ++ notify: function(t, str, details) { ++ this.ncond = this.ncond || ['proc', 'ext', 'state']; ++ if(this.ncond.indexOf(t) < 0) return; ++ Main.notify(str, details || ""); ++ }, ++}); ++ ++// lazy-evaluation ++let logger = null; ++function getLogger() { ++ if(logger === null) ++ logger = new Logger("gnome-shell"); ++ return logger; ++} ++ ++class Extension { ++ constructor(uuid) { ++ this._uuid = uuid; ++ ++ ExtensionUtils.initTranslations(GETTEXT_DOMAIN); ++ } ++ ++ enable() { ++ BackgroundMenu.BackgroundMenu = CustomBackgroundMenu; ++ Main.layoutManager._updateBackgrounds(); ++ } ++ ++ disable() { ++ BackgroundMenu.BackgroundMenu = OriginalBackgroundMenu; ++ Main.layoutManager._updateBackgrounds(); ++ } ++} ++ ++function init(meta) { ++ return new Extension(meta.uuid); ++} +diff --git a/extensions/custom-menu/meson.build b/extensions/custom-menu/meson.build +new file mode 100644 +index 00000000..92450963 +--- /dev/null ++++ b/extensions/custom-menu/meson.build +@@ -0,0 +1,7 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) ++ ++extension_sources += files('config.js') +diff --git a/extensions/custom-menu/metadata.json.in b/extensions/custom-menu/metadata.json.in +new file mode 100644 +index 00000000..054f639b +--- /dev/null ++++ b/extensions/custom-menu/metadata.json.in +@@ -0,0 +1,10 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Custom menu", ++"description": "Quick custom menu for launching your favorite applications", ++"shell-version": [ "@shell_current@" ], ++"url": "@url@" ++} +diff --git a/extensions/custom-menu/stylesheet.css b/extensions/custom-menu/stylesheet.css +new file mode 100644 +index 00000000..25134b65 +--- /dev/null ++++ b/extensions/custom-menu/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index 75a2beaa..b0c94fe4 100644 +--- a/meson.build ++++ b/meson.build +@@ -51,6 +51,7 @@ all_extensions = default_extensions + all_extensions += [ + 'auto-move-windows', + 'classification-banner', ++ 'custom-menu', + 'dash-to-dock', + 'dash-to-panel', + 'disable-screenshield', +-- +2.38.1 + diff --git a/SOURCES/add-workspace-tooltips.patch b/SOURCES/add-workspace-tooltips.patch new file mode 100644 index 0000000..c809a48 --- /dev/null +++ b/SOURCES/add-workspace-tooltips.patch @@ -0,0 +1,176 @@ +From 1f9f4af38f991b462ee5f872a697d88a9e115499 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 20 Jan 2021 20:18:39 +0100 +Subject: [PATCH 1/2] workspace-indicator: Add tooltips to workspace thumbnails + +When showing previews instead of the menu, the workspace names from +our preferences don't appear anywhere. Some users care strongly about +those, so expose them as tooltip on hover. +--- + extensions/workspace-indicator/extension.js | 40 +++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 69eef88c..b10e37ff 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -8,6 +8,7 @@ const ExtensionUtils = imports.misc.extensionUtils; + const Main = imports.ui.main; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; +@@ -15,6 +16,9 @@ const _ = Gettext.gettext; + const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; + const WORKSPACE_KEY = 'workspace-names'; + ++const TOOLTIP_OFFSET = 6; ++const TOOLTIP_ANIMATION_TIME = 150; ++ + let WindowPreview = GObject.registerClass({ + GTypeName: 'WorkspaceIndicatorWindowPreview' + }, class WindowPreview extends St.Button { +@@ -117,7 +121,14 @@ let WorkspaceThumbnail = GObject.registerClass({ + y_fill: true + }); + ++ this._tooltip = new St.Label({ ++ style_class: 'dash-label', ++ visible: false, ++ }); ++ Main.uiGroup.add_child(this._tooltip); ++ + this.connect('destroy', this._onDestroy.bind(this)); ++ this.connect('notify::hover', this._syncTooltip.bind(this)); + + this._index = index; + this._delegate = this; // needed for DND +@@ -204,7 +215,36 @@ let WorkspaceThumbnail = GObject.registerClass({ + ws.activate(global.get_current_time()); + } + ++ _syncTooltip() { ++ if (this.hover) { ++ this._tooltip.text = Meta.prefs_get_workspace_name(this._index); ++ this._tooltip.opacity = 0; ++ this._tooltip.show(); ++ ++ const [stageX, stageY] = this.get_transformed_position(); ++ const thumbWidth = this.allocation.get_width(); ++ const thumbHeight = this.allocation.get_height(); ++ const tipWidth = this._tooltip.width; ++ const xOffset = Math.floor((thumbWidth - tipWidth) / 2); ++ const monitor = Main.layoutManager.findMonitorForActor(this); ++ const x = Math.min( ++ Math.max(stageX + xOffset, monitor.x), ++ monitor.x + monitor.width - tipWidth); ++ const y = stageY + thumbHeight + TOOLTIP_OFFSET; ++ this._tooltip.set_position(x, y); ++ } ++ ++ Tweener.addTween(this._tooltip, { ++ opacity: this.hover ? 255 : 0, ++ time: TOOLTIP_ANIMATION_TIME * 1000, ++ transition: 'easeOutQuad', ++ onComplete: () => (this._tooltip.visible = this.hover), ++ }); ++ } ++ + _onDestroy() { ++ this._tooltip.destroy(); ++ + this._workspace.disconnect(this._windowAddedId); + this._workspace.disconnect(this._windowRemovedId); + global.display.disconnect(this._restackedId); +-- +2.31.1 + + +From 19e19e11214b6b9deae110cd6a4c9232d77c18cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 20 Jan 2021 20:29:01 +0100 +Subject: [PATCH 2/2] window-list: Add tooltips to workspace thumbnails + +When showing previews instead of the menu, the workspace names +don't appear anywhere. Some users care strongly about those, so +expose them as tooltip on hover. +--- + extensions/window-list/workspaceIndicator.js | 40 ++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index ca476111..33ec9b0e 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -5,10 +5,14 @@ const DND = imports.ui.dnd; + const Main = imports.ui.main; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + ++const TOOLTIP_OFFSET = 6; ++const TOOLTIP_ANIMATION_TIME = 150; ++ + let WindowPreview = GObject.registerClass({ + GTypeName: 'WindowListWindowPreview' + }, class WindowPreview extends St.Button { +@@ -111,7 +115,14 @@ let WorkspaceThumbnail = GObject.registerClass({ + y_fill: true + }); + ++ this._tooltip = new St.Label({ ++ style_class: 'dash-label', ++ visible: false, ++ }); ++ Main.uiGroup.add_child(this._tooltip); ++ + this.connect('destroy', this._onDestroy.bind(this)); ++ this.connect('notify::hover', this._syncTooltip.bind(this)); + + this._index = index; + this._delegate = this; // needed for DND +@@ -198,7 +209,36 @@ let WorkspaceThumbnail = GObject.registerClass({ + ws.activate(global.get_current_time()); + } + ++ _syncTooltip() { ++ if (this.hover) { ++ this._tooltip.text = Meta.prefs_get_workspace_name(this._index); ++ this._tooltip.opacity = 0; ++ this._tooltip.show(); ++ ++ const [stageX, stageY] = this.get_transformed_position(); ++ const thumbWidth = this.allocation.get_width(); ++ const tipWidth = this._tooltip.width; ++ const tipHeight = this._tooltip.height; ++ const xOffset = Math.floor((thumbWidth - tipWidth) / 2); ++ const monitor = Main.layoutManager.findMonitorForActor(this); ++ const x = Math.min( ++ Math.max(stageX + xOffset, monitor.x), ++ monitor.x + monitor.width - tipWidth); ++ const y = stageY - tipHeight - TOOLTIP_OFFSET; ++ this._tooltip.set_position(x, y); ++ } ++ ++ Tweener.addTween(this._tooltip, { ++ opacity: this.hover ? 255 : 0, ++ time: TOOLTIP_ANIMATION_TIME * 1000, ++ transition: 'easeOutQuad', ++ onComplete: () => (this._tooltip.visible = this.hover), ++ }); ++ } ++ + _onDestroy() { ++ this._tooltip.destroy(); ++ + this._workspace.disconnect(this._windowAddedId); + this._workspace.disconnect(this._windowRemovedId); + global.display.disconnect(this._restackedId); +-- +2.31.1 + diff --git a/SOURCES/desktop-icons-touch-support.patch b/SOURCES/desktop-icons-touch-support.patch new file mode 100644 index 0000000..d596c7f --- /dev/null +++ b/SOURCES/desktop-icons-touch-support.patch @@ -0,0 +1,267 @@ +From bcbf9709802e7644c5911615dabdee7d8ca07719 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 31 May 2021 19:29:34 +0200 +Subject: [PATCH 1/3] desktopManager: Handle TOUCH_UPDATE/END events explicitly + for rubberband + +These events need specific handling for Wayland, as we do not get emulated +pointer events in that platform. Handle these for rubberband selection. +--- + extensions/desktop-icons/desktopManager.js | 67 ++++++++++++++++------ + 1 file changed, 48 insertions(+), 19 deletions(-) + +diff --git a/extensions/desktop-icons/desktopManager.js b/extensions/desktop-icons/desktopManager.js +index 399aee0..a70cd98 100644 +--- a/extensions/desktop-icons/desktopManager.js ++++ b/extensions/desktop-icons/desktopManager.js +@@ -130,26 +130,49 @@ var DesktopManager = GObject.registerClass({ + } + [x, y] = event.get_coords(); + this._updateRubberBand(x, y); +- let x0, y0, x1, y1; +- if (x >= this._rubberBandInitialX) { +- x0 = this._rubberBandInitialX; +- x1 = x; +- } else { +- x1 = this._rubberBandInitialX; +- x0 = x; +- } +- if (y >= this._rubberBandInitialY) { +- y0 = this._rubberBandInitialY; +- y1 = y; +- } else { +- y1 = this._rubberBandInitialY; +- y0 = y; +- } +- for (let [fileUri, fileItem] of this._fileItems) { +- fileItem.emit('selected', true, true, +- fileItem.intersectsWith(x0, y0, x1 - x0, y1 - y0)); +- } ++ this._updateSelection(x, y); + }); ++ this._rubberBandTouchId = global.stage.connect('touch-event', (actor, event) => { ++ // Let x11 pointer emulation do the job on X11 ++ if (!Meta.is_wayland_compositor()) ++ return Clutter.EVENT_PROPAGATE; ++ if (!global.display.is_pointer_emulating_sequence(event.get_event_sequence())) ++ return Clutter.EVENT_PROPAGATE; ++ ++ if (event.type() == Clutter.EventType.TOUCH_END) { ++ this.endRubberBand(); ++ return Clutter.EVENT_STOP; ++ } else if (event.type() == Clutter.EventType.TOUCH_UPDATE) { ++ [x, y] = event.get_coords(); ++ this._updateRubberBand(x, y); ++ this._updateSelection(x, y); ++ return Clutter.EVENT_STOP; ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ }); ++ } ++ ++ _updateSelection(x, y) { ++ let x0, y0, x1, y1; ++ if (x >= this._rubberBandInitialX) { ++ x0 = this._rubberBandInitialX; ++ x1 = x; ++ } else { ++ x1 = this._rubberBandInitialX; ++ x0 = x; ++ } ++ if (y >= this._rubberBandInitialY) { ++ y0 = this._rubberBandInitialY; ++ y1 = y; ++ } else { ++ y1 = this._rubberBandInitialY; ++ y0 = y; ++ } ++ for (let [fileUri, fileItem] of this._fileItems) { ++ fileItem.emit('selected', true, true, ++ fileItem.intersectsWith(x0, y0, x1 - x0, y1 - y0)); ++ } + } + + endRubberBand() { +@@ -157,8 +180,10 @@ var DesktopManager = GObject.registerClass({ + Extension.lockActivitiesButton = false; + this._grabHelper.ungrab(); + global.stage.disconnect(this._rubberBandId); ++ global.stage.disconnect(this._rubberBandTouchId); + global.stage.disconnect(this._stageReleaseEventId); + this._rubberBandId = 0; ++ this._rubberBandTouchId = 0; + this._stageReleaseEventId = 0; + + this._selection = new Set([...this._selection, ...this._currentSelection]); +@@ -739,6 +764,10 @@ var DesktopManager = GObject.registerClass({ + global.stage.disconnect(this._rubberBandId); + this._rubberBandId = 0; + ++ if (this._rubberBandTouchId) ++ global.stage.disconnect(this._rubberBandTouchId); ++ this._rubberBandTouchId = 0; ++ + this._rubberBand.destroy(); + + if (this._queryFileInfoCancellable) +-- +2.31.1 + + +From 0733004ffeb517f7a80ff41e7181027e8b92b17e Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 31 May 2021 19:31:03 +0200 +Subject: [PATCH 2/3] desktopGrid: Handle TOUCH_BEGIN events explicitly + +We do not get pointer emulated events on Wayland, so touch events should +be handled explicitly there. Handle starting rubberband selection via +touch. +--- + extensions/desktop-icons/desktopGrid.js | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/extensions/desktop-icons/desktopGrid.js b/extensions/desktop-icons/desktopGrid.js +index 94d2dfd..602fa7f 100644 +--- a/extensions/desktop-icons/desktopGrid.js ++++ b/extensions/desktop-icons/desktopGrid.js +@@ -21,6 +21,7 @@ const Clutter = imports.gi.Clutter; + const St = imports.gi.St; + const Gio = imports.gi.Gio; + const GLib = imports.gi.GLib; ++const Meta = imports.gi.Meta; + const Shell = imports.gi.Shell; + + const Signals = imports.signals; +@@ -123,6 +124,7 @@ var DesktopGrid = class { + () => this._backgroundDestroyed()); + + this._grid.connect('button-press-event', (actor, event) => this._onPressButton(actor, event)); ++ this._grid.connect('touch-event', (actor, event) => this._onTouchEvent(actor, event)); + + this._grid.connect('key-press-event', this._onKeyPress.bind(this)); + +@@ -506,6 +508,23 @@ var DesktopGrid = class { + return Clutter.EVENT_PROPAGATE; + } + ++ _onTouchEvent(actor, event) { ++ // Let x11 pointer emulation do the job on X11 ++ if (!Meta.is_wayland_compositor()) ++ return Clutter.EVENT_PROPAGATE; ++ ++ if (event.type() == Clutter.EventType.TOUCH_BEGIN && ++ global.display.is_pointer_emulating_sequence(event.get_event_sequence())) { ++ Extension.desktopManager.clearSelection(); ++ let [x, y] = event.get_coords(); ++ let [gridX, gridY] = this._grid.get_transformed_position(); ++ Extension.desktopManager.startRubberBand(x, y, gridX, gridY); ++ return Clutter.EVENT_STOP; ++ } ++ ++ return Clutter.EVENT_PROPAGATE; ++ } ++ + _addDesktopBackgroundMenu() { + this.actor._desktopBackgroundMenu = this._createDesktopBackgroundMenu(); + this.actor._desktopBackgroundManager = new PopupMenu.PopupMenuManager({ actor: this.actor }); +-- +2.31.1 + + +From 2d978ffc58562c4f4d00b1afb03da58be3102e29 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 31 May 2021 19:31:50 +0200 +Subject: [PATCH 3/3] fileItem: Handle (multi) touch explicitly via touch + events + +Wayland does not get pointer emulated events, so we must handle TOUCH_BEGIN/ +END here for file clicking/tapping to work there. +--- + extensions/desktop-icons/fileItem.js | 34 ++++++++++++++++++++++++---- + 1 file changed, 30 insertions(+), 4 deletions(-) + +diff --git a/extensions/desktop-icons/fileItem.js b/extensions/desktop-icons/fileItem.js +index 143cb9b..1cb47e8 100644 +--- a/extensions/desktop-icons/fileItem.js ++++ b/extensions/desktop-icons/fileItem.js +@@ -117,6 +117,7 @@ var FileItem = class { + this._container.connect('motion-event', (actor, event) => this._onMotion(actor, event)); + this._container.connect('leave-event', (actor, event) => this._onLeave(actor, event)); + this._container.connect('button-release-event', (actor, event) => this._onReleaseButton(actor, event)); ++ this._container.connect('touch-event', (actor, event) => this._onTouchEvent(actor, event)); + + /* Set the metadata and update relevant UI */ + this._updateMetadataFromFileInfo(fileInfo); +@@ -648,16 +649,26 @@ var FileItem = class { + DesktopIconsUtil.launchTerminal(this.file.get_path()); + } + ++ _eventButton(event) { ++ // Emulate button1 press on touch events ++ if (event.type() == Clutter.EventType.TOUCH_BEGIN || ++ event.type() == Clutter.EventType.TOUCH_END || ++ event.type() == Clutter.EventType.TOUCH_UPDATE) ++ return 1; ++ ++ return event.get_button(); ++ } ++ + _updateClickState(event) { + let settings = Clutter.Settings.get_default(); +- if ((event.get_button() == this._lastClickButton) && ++ if ((this._eventButton(event) == this._lastClickButton) && + ((event.get_time() - this._lastClickTime) < settings.double_click_time)) + this._clickCount++; + else + this._clickCount = 1; + + this._lastClickTime = event.get_time(); +- this._lastClickButton = event.get_button(); ++ this._lastClickButton = this._eventButton(event); + } + + _getClickCount() { +@@ -666,7 +677,7 @@ var FileItem = class { + + _onPressButton(actor, event) { + this._updateClickState(event); +- let button = event.get_button(); ++ let button = this._eventButton(event); + if (button == 3) { + if (!this.isSelected) + this.emit('selected', false, false, true); +@@ -725,7 +736,7 @@ var FileItem = class { + } + + _onReleaseButton(actor, event) { +- let button = event.get_button(); ++ let button = this._eventButton(event); + if (button == 1) { + // primaryButtonPressed is TRUE only if the user has pressed the button + // over an icon, and if (s)he has not started a drag&drop operation +@@ -744,6 +755,21 @@ var FileItem = class { + return Clutter.EVENT_PROPAGATE; + } + ++ _onTouchEvent(actor, event) { ++ // Let x11 pointer emulation do the job on X11 ++ if (!Meta.is_wayland_compositor()) ++ return Clutter.EVENT_PROPAGATE; ++ if (!global.display.is_pointer_emulating_sequence(event.get_event_sequence())) ++ return Clutter.EVENT_PROPAGATE; ++ ++ if (event.type() == Clutter.EventType.TOUCH_BEGIN) ++ this._onPressButton(actor, event); ++ else if (event.type() == Clutter.EventType.TOUCH_UPDATE) ++ this._onMotion(actor, event); ++ else if (event.type() == Clutter.EventType.TOUCH_END) ++ this._onReleaseButton(actor, event); ++ } ++ + get savedCoordinates() { + return this._savedCoordinates; + } +-- +2.31.1 + diff --git a/SOURCES/gnome-classic-wayland.desktop b/SOURCES/gnome-classic-wayland.desktop new file mode 100644 index 0000000..bf02a49 --- /dev/null +++ b/SOURCES/gnome-classic-wayland.desktop @@ -0,0 +1,27 @@ +[Desktop Entry] +Name[de]=Klassisch (Wayland Anzeige-Server) +Name[es]=Clásico (servidor gráfico Wayland) +Name[fr]=Classic (serveur affichage Wayland) +Name[it]=Classico (server grafico Wayland) +Name[ja]=クラシック (Wayland ディスプレイサーバー) +Name[ko]=클래식 (Wayland 디스플레이 서버) +Name[pt_BR]=Clássico (servidor de exibição Wayland) +Name[ru]=Классический (дисплейный сервер Wayland) +Name[zh_CN]=经典(Wayland 显现服务器) +Name[zh_TW]=經典(Wayland顯示服務器) +Name=Classic (Wayland display server) +Comment[de]=Diese Sitzung meldet Sie in GNOME Classic an +Comment[es]=Esta sesión inicia GNOME clásico +Comment[fr]=Cette session vous connnecte à GNOME Classique +Comment[it]=Questa sessione si avvia con GNOME classico +Comment[ja]=GNOME クラシックモードでログインします +Comment[ko]=이 세션을 사용하면 그놈 클래식에 로그인합니다 +Comment[pt_BR]=Essa sessão se inicia como GNOME Clássico +Comment[ru]=Данный сеанс использует классический рабочий стол GNOME +Comment[zh_CN]=该会话将登录到“GNOME 经典模式” +Comment[zh_TW]=這個作業階段讓您登入 GNOME Classic +Comment=This session logs you into GNOME Classic +Exec=env GNOME_SHELL_SESSION_MODE=classic gnome-session --session gnome-classic +TryExec=gnome-session +Type=Application +DesktopNames=GNOME-Classic;GNOME; diff --git a/SOURCES/gnome-classic.desktop b/SOURCES/gnome-classic.desktop new file mode 100644 index 0000000..b59c0d9 --- /dev/null +++ b/SOURCES/gnome-classic.desktop @@ -0,0 +1,27 @@ +[Desktop Entry] +Name[de]=Klassisch (X11 Anzeige-Server) +Name[es]=Clásico (servidor gráfico X11) +Name[fr]=Classic (serveur affichage X11) +Name[it]=Classico (server grafico X11) +Name[ja]=クラシック (X11 ディスプレイサーバー) +Name[ko]=클래식 (X11 디스플레이 서버) +Name[pt_BR]=Clássico (servidor de exibição X11) +Name[ru]=Классический (дисплейный сервер X11) +Name[zh_CN]=经典(X11 显示服务器) +Name[zh_TW]=經典(X11顯示服務器) +Name=Classic (X11 display server) +Comment[de]=Diese Sitzung meldet Sie in GNOME Classic an +Comment[es]=Esta sesión inicia GNOME clásico +Comment[fr]=Cette session vous connnecte à GNOME Classique +Comment[it]=Questa sessione si avvia con GNOME classico +Comment[ja]=GNOME クラシックモードでログインします +Comment[ko]=이 세션을 사용하면 그놈 클래식에 로그인합니다 +Comment[pt_BR]=Essa sessão se inicia como GNOME Clássico +Comment[ru]=Данный сеанс использует классический рабочий стол GNOME +Comment[zh_CN]=该会话将登录到“GNOME 经典模式” +Comment[zh_TW]=這個作業階段讓您登入 GNOME Classic +Comment=This session logs you into GNOME Classic +Exec=env GNOME_SHELL_SESSION_MODE=classic gnome-session --session gnome-classic +TryExec=gnome-session +Type=Application +DesktopNames=GNOME-Classic;GNOME; diff --git a/SOURCES/more-classic-classic-mode.patch b/SOURCES/more-classic-classic-mode.patch new file mode 100644 index 0000000..5f0d85b --- /dev/null +++ b/SOURCES/more-classic-classic-mode.patch @@ -0,0 +1,3270 @@ +From e8425ac158bda015b09861bab4224ca2fdd2b50f Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Mon, 15 Jul 2019 23:40:09 +0200 +Subject: [PATCH 01/30] classic: hover state for panel buttons + +- prelight before active +- lighten up slightly, similar to what the default does (inverted) + +Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/169 +--- + data/gnome-classic.scss | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/data/gnome-classic.scss b/data/gnome-classic.scss +index 9e23506..9c0e06e 100644 +--- a/data/gnome-classic.scss ++++ b/data/gnome-classic.scss +@@ -32,18 +32,20 @@ $variant: 'light'; + font-weight: normal; + color: $fg_color; + text-shadow: none; ++ &:hover { ++ color: lighten($fg_color,10%); ++ text-shadow: none; ++ & .system-status-icon { icon-shadow: none; } ++ } + &:active, &:overview, &:focus, &:checked { + // Trick due to St limitations. It needs a background to draw + // a box-shadow +- background-color: $selected_bg_color !important; +- color: $selected_fg_color !important; ++ background-color: $selected_bg_color; ++ color: $selected_fg_color; + box-shadow: none; + & > .system-status-icon { icon-shadow: none; } + } +- &:hover { +- text-shadow: none; +- & .system-status-icon { icon-shadow: none; } +- } ++ + .app-menu-icon { width: 0; height: 0; margin: 0; } // shell's display:none; :D + + .system-status-icon { +-- +2.21.0 + + +From fcbb1b1d8956d7447973a9d5ffaa4fede8d359ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 18 Jul 2019 00:39:49 +0200 +Subject: [PATCH 02/30] apps-menu: Add drop-shadow to application icons + +... to make sure they are readable on light backgrounds. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/168 +--- + extensions/apps-menu/extension.js | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index cc399c6..1f95c16 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -103,7 +103,9 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { + } + + _updateIcon() { +- this._iconBin.set_child(this.getDragActor()); ++ let icon = this.getDragActor(); ++ icon.style_class = 'icon-dropshadow'; ++ this._iconBin.set_child(icon); + } + } + +-- +2.21.0 + + +From 904e632c62aab6cd89a849a01c56b7c0f123eee8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 29 May 2019 10:17:20 +0000 +Subject: [PATCH 03/30] places-menu: Don't hardcode position + +The extension currently assumes that we have the "Activities" button +at the left of the top bar. This is currently true, not only in the +regular session, but also in GNOME classic where the button is hidden +(but still present). + +However this is about to change: We will stop taking over the button +from the apps-menu extension, and instead disable "Activities" from +the session mode definition. + +Prepare for this by adding the places menu before the application menu +instead of assuming a hardcoded position. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 +--- + extensions/places-menu/extension.js | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/extensions/places-menu/extension.js b/extensions/places-menu/extension.js +index c477a4a..5c038ae 100644 +--- a/extensions/places-menu/extension.js ++++ b/extensions/places-menu/extension.js +@@ -135,9 +135,9 @@ let _indicator; + function enable() { + _indicator = new PlacesMenu; + +- let pos = 1; ++ let pos = Main.sessionMode.panel.left.indexOf('appMenu'); + if ('apps-menu' in Main.panel.statusArea) +- pos = 2; ++ pos++; + Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left'); + } + +-- +2.21.0 + + +From 2b1eb285d0c0e113a9be2bd801e1692b48fcfd78 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 29 May 2019 08:32:03 +0000 +Subject: [PATCH 04/30] apps-menu: Stop taking over Activities button + +We don't want the "Activities" button in GNOME Classic, but the current +way of handling it is confusing: + + - the button is hidden, but the corresponding hot corner + sometimes works (when the application menu isn't open) + + - the button is effectively moved inside the menu, although + it's clearly not an app or category + + - the apps-menu can be used independent from classic mode, in + which case removing the "Activities" button may not be wanted + +Address those points by removing any handling of the activities button +from the apps-menu extension. We will remove it again from the classic +session via a session mode tweak. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 +--- + extensions/apps-menu/extension.js | 67 +++---------------------------- + 1 file changed, 6 insertions(+), 61 deletions(-) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index 1f95c16..865a87e 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -25,22 +25,6 @@ const NAVIGATION_REGION_OVERSHOOT = 50; + Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish'); + Gio._promisify(Gio._LocalFilePrototype, 'set_attributes_async', 'set_attributes_finish'); + +-class ActivitiesMenuItem extends PopupMenu.PopupBaseMenuItem { +- constructor(button) { +- super(); +- this._button = button; +- let label = new St.Label({ text: _('Activities Overview') }); +- this.actor.add_child(label); +- this.actor.label_actor = label; +- } +- +- activate(event) { +- this._button.menu.toggle(); +- Main.overview.toggle(); +- super.activate(event); +- } +-} +- + class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { + constructor(button, app) { + super(); +@@ -235,21 +219,6 @@ class ApplicationsMenu extends PopupMenu.PopupMenu { + return false; + } + +- open(animate) { +- this._button.hotCorner.setBarrierSize(0); +- if (this._button.hotCorner.actor) // fallback corner +- this._button.hotCorner.actor.hide(); +- super.open(animate); +- } +- +- close(animate) { +- let size = Main.layoutManager.panelBox.height; +- this._button.hotCorner.setBarrierSize(size); +- if (this._button.hotCorner.actor) // fallback corner +- this._button.hotCorner.actor.show(); +- super.close(animate); +- } +- + toggle() { + if (this.isOpen) { + this._button.selectCategory(null); +@@ -383,7 +352,7 @@ Signals.addSignalMethods(DesktopTarget.prototype); + + let ApplicationsButton = GObject.registerClass( + class ApplicationsButton extends PanelMenu.Button { +- _init() { ++ _init(includeIcon) { + super._init(1.0, null, false); + + this.setMenu(new ApplicationsMenu(this, 1.0, St.Side.TOP, this)); +@@ -400,7 +369,8 @@ class ApplicationsButton extends PanelMenu.Button { + '/usr/share/icons/hicolor/scalable/apps/start-here.svg'); + this._icon = new St.Icon({ + gicon: new Gio.FileIcon({ file: iconFile }), +- style_class: 'panel-logo-icon' ++ style_class: 'panel-logo-icon', ++ visible: includeIcon + }); + hbox.add_actor(this._icon); + +@@ -416,8 +386,6 @@ class ApplicationsButton extends PanelMenu.Button { + this.name = 'panelApplications'; + this.label_actor = this._label; + +- this.connect('captured-event', this._onCapturedEvent.bind(this)); +- + this._showingId = Main.overview.connect('showing', () => { + this.add_accessible_state (Atk.StateType.CHECKED); + }); +@@ -459,10 +427,6 @@ class ApplicationsButton extends PanelMenu.Button { + } + } + +- get hotCorner() { +- return Main.layoutManager.hotCorners[Main.layoutManager.primaryIndex]; +- } +- + _createVertSeparator() { + let separator = new St.DrawingArea({ + style_class: 'calendar-vertical-separator', +@@ -489,14 +453,6 @@ class ApplicationsButton extends PanelMenu.Button { + this._desktopTarget.destroy(); + } + +- _onCapturedEvent(actor, event) { +- if (event.type() == Clutter.EventType.BUTTON_PRESS) { +- if (!Main.overview.shouldToggleByCornerOrButton()) +- return true; +- } +- return false; +- } +- + _onMenuKeyPress(actor, event) { + let symbol = event.get_key_symbol(); + if (symbol == Clutter.KEY_Left || symbol == Clutter.KEY_Right) { +@@ -640,14 +596,6 @@ class ApplicationsButton extends PanelMenu.Button { + y_align: St.Align.START + }); + +- let activities = new ActivitiesMenuItem(this); +- this.leftBox.add(activities.actor, { +- expand: false, +- x_fill: true, +- y_fill: false, +- y_align: St.Align.START +- }); +- + this.applicationsBox = new St.BoxLayout({ vertical: true }); + this.applicationsScrollBox.add_actor(this.applicationsBox); + this.categoriesBox = new St.BoxLayout({ vertical: true }); +@@ -759,19 +707,16 @@ class ApplicationsButton extends PanelMenu.Button { + }); + + let appsMenuButton; +-let activitiesButton; + + function enable() { +- activitiesButton = Main.panel.statusArea['activities']; +- activitiesButton.container.hide(); +- appsMenuButton = new ApplicationsButton(); +- Main.panel.addToStatusArea('apps-menu', appsMenuButton, 1, 'left'); ++ let index = Main.sessionMode.panel.left.indexOf('activities') + 1; ++ appsMenuButton = new ApplicationsButton(index == 0); ++ Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left'); + } + + function disable() { + Main.panel.menuManager.removeMenu(appsMenuButton.menu); + appsMenuButton.destroy(); +- activitiesButton.container.show(); + } + + function init() { +-- +2.21.0 + + +From 45b5f9b8f73032a87017131d8f29b429a8b75ef1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 7 Jun 2019 14:30:16 +0000 +Subject: [PATCH 05/30] apps-menu: Stop hiding the overview when toggled + +Now that the extension no longer doubles as the "Activities" button, +that behavior is confusing. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 +--- + extensions/apps-menu/extension.js | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index 865a87e..1e2882b 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -220,12 +220,8 @@ class ApplicationsMenu extends PopupMenu.PopupMenu { + } + + toggle() { +- if (this.isOpen) { ++ if (this.isOpen) + this._button.selectCategory(null); +- } else { +- if (Main.overview.visible) +- Main.overview.hide(); +- } + super.toggle(); + } + } +-- +2.21.0 + + +From 0f143dc87bd501a44843aad7d0a1cd0d20ad4d31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 7 Jun 2019 20:07:19 +0000 +Subject: [PATCH 06/30] apps-menu: Hide overview when launching app + +Now that we no longer hide the overview when the menu is opened, +it is possible to activate menu entries from the overview. Start +hiding the overview in that case, which is consistent with app +launching elsewhere. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 +--- + extensions/apps-menu/extension.js | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/extensions/apps-menu/extension.js b/extensions/apps-menu/extension.js +index 1e2882b..3dbe43f 100644 +--- a/extensions/apps-menu/extension.js ++++ b/extensions/apps-menu/extension.js +@@ -66,6 +66,8 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem { + this._button.selectCategory(null); + this._button.menu.toggle(); + super.activate(event); ++ ++ Main.overview.hide(); + } + + setActive(active, params) { +-- +2.21.0 + + +From 72f956cc589d9789ae6ad7b99c1dfd60f9a9f8e3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 29 May 2019 09:44:30 +0000 +Subject: [PATCH 07/30] classic: Disable overview + +The overview is one of the defining features of GNOME 3, and thus +almost by definition at odds with the classic session, which +emulates a traditional GNOME 2 desktop. + +Even with the less prominent placement inside the application menu +it never quite fit in - it doesn't help that besides the different +UI paradigma, the overview keeps its "normal" styling which differs +greatly with classic's normal mode. + +So besides removing the "Activities" button via the session mode +definition, now that the apps-menu extension doesn't replace it anymore, +disable the overview completely in the classic session. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69 +--- + data/classic.json.in | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/data/classic.json.in b/data/classic.json.in +index fdb3762..c1c0544 100644 +--- a/data/classic.json.in ++++ b/data/classic.json.in +@@ -1,8 +1,9 @@ + { + "parentMode": "user", + "stylesheetName": "gnome-classic.css", ++ "hasOverview": false, + "enabledExtensions": [@CLASSIC_EXTENSIONS@], +- "panel": { "left": ["activities", "appMenu"], ++ "panel": { "left": ["appMenu"], + "center": [], + "right": ["a11y", "keyboard", "dateMenu", "aggregateMenu"] + } +-- +2.21.0 + + +From 6277f55210a2f1a3283b3eaad7ae1f2cf2f48d8b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 14 May 2019 19:51:22 +0200 +Subject: [PATCH 08/30] window-list: Add window picker button +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With the latest changes, GNOME Classic has become so classic that it +is bordering dull. Salvage at least a tiny piece of GNOME 3 in form +of a window-pick button which toggles an exposé-like reduced overview. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/73 +--- + extensions/window-list/classic.css | 20 +- + extensions/window-list/extension.js | 36 +++- + extensions/window-list/meson.build | 2 +- + extensions/window-list/stylesheet.css | 27 ++- + extensions/window-list/windowPicker.js | 260 +++++++++++++++++++++++++ + 5 files changed, 332 insertions(+), 13 deletions(-) + create mode 100644 extensions/window-list/windowPicker.js + +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index f3c44a3..c506bea 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -6,14 +6,13 @@ + height: 2.25em ; + } + +- .bottom-panel .window-button > StWidget { ++ .bottom-panel .window-button > StWidget, ++ .bottom-panel .window-picker-toggle > StWidget { + background-gradient-drection: vertical; + background-color: #fff; + background-gradient-start: #fff; + background-gradient-end: #eee; + color: #000; +- -st-natural-width: 18.7em; +- max-width: 18.75em; + color: #2e3436; + background-color: #eee; + border-radius: 2px; +@@ -22,7 +21,17 @@ + text-shadow: 0 0 transparent; + } + +- .bottom-panel .window-button:hover > StWidget { ++ .bottom-panel .window-button > StWidget { ++ -st-natural-width: 18.7em; ++ max-width: 18.75em; ++ } ++ ++ .bottom-panel .window-picker-toggle > StWidet { ++ border: 1px solid rgba(0,0,0,0.3); ++ } ++ ++ .bottom-panel .window-button:hover > StWidget, ++ .bottom-panel .window-picker-toggle:hover > StWidget { + background-color: #f9f9f9; + } + +@@ -31,7 +40,8 @@ + box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5); + } + +- .bottom-panel .window-button.focused > StWidget { ++ .bottom-panel .window-button.focused > StWidget, ++ .bottom-panel .window-picker-toggle:checked > StWidget { + background-color: #ddd; + box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5); + } +diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js +index e1ea742..b2784b4 100644 +--- a/extensions/window-list/extension.js ++++ b/extensions/window-list/extension.js +@@ -3,11 +3,14 @@ const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi; + + const DND = imports.ui.dnd; + const Main = imports.ui.main; ++const Overview = imports.ui.overview; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; ++const Tweener = imports.ui.tweener; + + const ExtensionUtils = imports.misc.extensionUtils; + const Me = ExtensionUtils.getCurrentExtension(); ++const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; +@@ -787,6 +790,12 @@ class WindowList { + let box = new St.BoxLayout({ x_expand: true, y_expand: true }); + this.actor.add_actor(box); + ++ let toggle = new WindowPickerToggle(); ++ box.add_actor(toggle); ++ ++ toggle.connect('notify::checked', ++ this._updateWindowListVisibility.bind(this)); ++ + let layout = new Clutter.BoxLayout({ homogeneous: true }); + this._windowList = new St.Widget({ + style_class: 'window-list', +@@ -936,6 +945,19 @@ class WindowList { + this._workspaceIndicator.actor.visible = hasWorkspaces && workspacesOnMonitor; + } + ++ _updateWindowListVisibility() { ++ let visible = !Main.windowPicker.visible; ++ ++ Tweener.addTween(this._windowList, { ++ opacity: visible ? 255 : 0, ++ transition: 'ease-out-quad', ++ time: Overview.ANIMATION_TIME ++ }); ++ ++ this._windowList.reactive = visible; ++ this._windowList.get_children().forEach(c => c.reactive = visible); ++ } ++ + _getPreferredUngroupedWindowListWidth() { + if (this._windowList.get_n_children() == 0) + return this._windowList.get_preferred_width(-1)[1]; +@@ -1206,7 +1228,7 @@ class WindowList { + class Extension { + constructor() { + this._windowLists = null; +- this._injections = {}; ++ this._hideOverviewOrig = Main.overview.hide; + } + + enable() { +@@ -1221,6 +1243,13 @@ class Extension { + Main.layoutManager.connect('monitors-changed', + this._buildWindowLists.bind(this)); + ++ Main.windowPicker = new WindowPicker(); ++ ++ Main.overview.hide = () => { ++ Main.windowPicker.close(); ++ this._hideOverviewOrig.call(Main.overview); ++ }; ++ + this._buildWindowLists(); + } + +@@ -1251,6 +1280,11 @@ class Extension { + windowList.actor.destroy(); + }); + this._windowLists = null; ++ ++ Main.windowPicker.actor.destroy(); ++ delete Main.windowPicker; ++ ++ Main.overview.hide = this._hideOverviewOrig; + } + + someWindowListContains(actor) { +diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build +index b4aa4db..5b1f5f5 100644 +--- a/extensions/window-list/meson.build ++++ b/extensions/window-list/meson.build +@@ -4,7 +4,7 @@ extension_data += configure_file( + configuration: metadata_conf + ) + +-extension_sources += files('prefs.js') ++extension_sources += files('prefs.js', 'windowPicker.js') + extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') + + if classic_mode_enabled +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index f5285cb..91383ab 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -26,9 +26,8 @@ + spacing: 4px; + } + +-.window-button > StWidget { +- -st-natural-width: 18.75em; +- max-width: 18.75em; ++.window-button > StWidget, ++.window-picker-toggle > StWidget { + color: #bbb; + background-color: black; + border-radius: 4px; +@@ -37,7 +36,21 @@ + text-shadow: 1px 1px 4px rgba(0,0,0,0.8); + } + +-.window-button:hover > StWidget { ++.window-picker-toggle { ++ padding: 3px; ++} ++ ++.window-picker-toggle > StWidet { ++ border: 1px solid rgba(255,255,255,0.3); ++} ++ ++.window-button > StWidget { ++ -st-natural-width: 18.75em; ++ max-width: 18.75em; ++} ++ ++.window-button:hover > StWidget, ++.window-picker-toggle:hover > StWidget { + color: white; + background-color: #1f1f1f; + } +@@ -47,12 +60,14 @@ + box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5); + } + +-.window-button.focused > StWidget { ++.window-button.focused > StWidget, ++.window-picker-toggle:checked > StWidget { + color: white; + box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7); + } + +-.window-button.focused:active > StWidget { ++.window-button.focused:active > StWidget, ++.window-picker-toggle:checked:active > StWidget { + box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7); + } + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js +new file mode 100644 +index 0000000..024fd80 +--- /dev/null ++++ b/extensions/window-list/windowPicker.js +@@ -0,0 +1,260 @@ ++/* exported WindowPicker, WindowPickerToggle */ ++const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; ++const Signals = imports.signals; ++ ++const Layout = imports.ui.layout; ++const Main = imports.ui.main; ++const Overview = imports.ui.overview; ++const { WorkspacesDisplay } = imports.ui.workspacesView; ++ ++let MyWorkspacesDisplay = class extends WorkspacesDisplay { ++ constructor() { ++ super(); ++ ++ this.actor.add_constraint( ++ new Layout.MonitorConstraint({ ++ primary: true, ++ work_area: true ++ })); ++ ++ this.actor.connect('destroy', this._onDestroy.bind(this)); ++ ++ this._workareasChangedId = global.display.connect('workareas-changed', ++ this._onWorkAreasChanged.bind(this)); ++ this._onWorkAreasChanged(); ++ } ++ ++ show(...args) { ++ if (this._scrollEventId == 0) ++ this._scrollEventId = Main.windowPicker.connect('scroll-event', ++ this._onScrollEvent.bind(this)); ++ ++ super.show(...args); ++ } ++ ++ hide(...args) { ++ if (this._scrollEventId > 0) ++ Main.windowPicker.disconnect(this._scrollEventId); ++ this._scrollEventId = 0; ++ ++ super.hide(...args); ++ } ++ ++ _onWorkAreasChanged() { ++ let { primaryIndex } = Main.layoutManager; ++ let workarea = Main.layoutManager.getWorkAreaForMonitor(primaryIndex); ++ this.setWorkspacesFullGeometry(workarea); ++ } ++ ++ _updateWorkspacesViews() { ++ super._updateWorkspacesViews(); ++ ++ this._workspacesViews.forEach(v => { ++ Main.layoutManager.overviewGroup.remove_actor(v.actor); ++ Main.windowPicker.actor.add_actor(v.actor); ++ }); ++ } ++ ++ _onDestroy() { ++ if (this._workareasChangedId) ++ global.display.disconnect(this._workareasChangedId); ++ this._workareasChangedId = 0; ++ } ++}; ++ ++var WindowPicker = class { ++ constructor() { ++ this._visible = false; ++ this._modal = false; ++ ++ this.actor = new Clutter.Actor(); ++ ++ this.actor.connect('destroy', this._onDestroy.bind(this)); ++ ++ global.bind_property('screen-width', ++ this.actor, 'width', ++ GObject.BindingFlags.SYNC_CREATE); ++ global.bind_property('screen-height', ++ this.actor, 'height', ++ GObject.BindingFlags.SYNC_CREATE); ++ ++ this._backgroundGroup = new Meta.BackgroundGroup({ reactive: true }); ++ this.actor.add_child(this._backgroundGroup); ++ ++ this._backgroundGroup.connect('scroll-event', (a, ev) => { ++ this.emit('scroll-event', ev); ++ }); ++ ++ // Trick WorkspacesDisplay constructor into adding actions here ++ let addActionOrig = Main.overview.addAction; ++ Main.overview.addAction = a => this._backgroundGroup.add_action(a); ++ ++ this._workspacesDisplay = new MyWorkspacesDisplay(); ++ this.actor.add_child(this._workspacesDisplay.actor); ++ ++ Main.overview.addAction = addActionOrig; ++ ++ this._bgManagers = []; ++ ++ this._monitorsChangedId = Main.layoutManager.connect('monitors-changed', ++ this._updateBackgrounds.bind(this)); ++ this._updateBackgrounds(); ++ ++ Main.uiGroup.insert_child_below(this.actor, global.window_group); ++ } ++ ++ get visible() { ++ return this._visible; ++ } ++ ++ open() { ++ if (this._visible) ++ return; ++ ++ this._visible = true; ++ ++ if (!this._syncGrab()) ++ return; ++ ++ this._fakeOverviewVisible(true); ++ this._shadeBackgrounds(); ++ this._fakeOverviewAnimation(); ++ this._workspacesDisplay.show(false); ++ ++ this.emit('open-state-changed', this._visible); ++ } ++ ++ close() { ++ if (!this._visible) ++ return; ++ ++ this._visible = false; ++ ++ if (!this._syncGrab()) ++ return; ++ ++ this._workspacesDisplay.animateFromOverview(false); ++ this._unshadeBackgrounds(); ++ this._fakeOverviewAnimation(() => { ++ this._workspacesDisplay.hide(); ++ this._fakeOverviewVisible(false); ++ }); ++ ++ this.emit('open-state-changed', this._visible); ++ } ++ ++ _fakeOverviewAnimation(onComplete) { ++ Main.overview.animationInProgress = true; ++ GLib.timeout_add( ++ GLib.PRIORITY_DEFAULT, ++ Overview.ANIMATION_TIME * 1000, ++ () => { ++ Main.overview.animationInProgress = false; ++ if (onComplete) ++ onComplete(); ++ }); ++ } ++ ++ _fakeOverviewVisible(visible) { ++ // Fake overview state for WorkspacesDisplay ++ Main.overview.visible = visible; ++ ++ // Hide real windows ++ Main.layoutManager._inOverview = visible; ++ Main.layoutManager._updateVisibility(); ++ } ++ ++ _syncGrab() { ++ if (this._visible) { ++ if (this._modal) ++ return true; ++ ++ this._modal = Main.pushModal(this.actor, { ++ actionMode: Shell.ActionMode.OVERVIEW ++ }); ++ ++ if (!this._modal) { ++ this.hide(); ++ return false; ++ } ++ } else if (this._modal) { ++ Main.popModal(this.actor); ++ this._modal = false; ++ } ++ return true; ++ } ++ ++ _onDestroy() { ++ if (this._monitorsChangedId) ++ Main.layoutManager.disconnect(this._monitorsChangedId); ++ this._monitorsChangedId = 0; ++ } ++ ++ _updateBackgrounds() { ++ Main.overview._updateBackgrounds.call(this); ++ } ++ ++ _shadeBackgrounds() { ++ Main.overview._shadeBackgrounds.call(this); ++ } ++ ++ _unshadeBackgrounds() { ++ Main.overview._unshadeBackgrounds.call(this); ++ } ++}; ++Signals.addSignalMethods(WindowPicker.prototype); ++ ++var WindowPickerToggle = GObject.registerClass( ++class WindowPickerToggle extends St.Button { ++ _init() { ++ let iconBin = new St.Widget({ ++ layout_manager: new Clutter.BinLayout() ++ }); ++ iconBin.add_child(new St.Icon({ ++ icon_name: 'focus-windows-symbolic', ++ icon_size: 16, ++ x_expand: true, ++ y_expand: true, ++ x_align: Clutter.ActorAlign.CENTER, ++ y_align: Clutter.ActorAlign.CENTER ++ })); ++ super._init({ ++ style_class: 'window-picker-toggle', ++ child: iconBin, ++ visible: !Main.sessionMode.hasOverview, ++ x_fill: true, ++ y_fill: true, ++ toggle_mode: true ++ }); ++ ++ this._overlayKeyId = 0; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ ++ this.connect('notify::checked', () => { ++ if (this.checked) ++ Main.windowPicker.open(); ++ else ++ Main.windowPicker.close(); ++ }); ++ ++ if (!Main.sessionMode.hasOverview) { ++ this._overlayKeyId = global.display.connect('overlay-key', () => { ++ if (!Main.windowPicker.visible) ++ Main.windowPicker.open(); ++ else ++ Main.windowPicker.close(); ++ }); ++ } ++ ++ Main.windowPicker.connect('open-state-changed', () => { ++ this.checked = Main.windowPicker.visible; ++ }); ++ } ++ ++ _onDestroy() { ++ if (this._overlayKeyId) ++ global.display.disconnect(this._overlayKeyId); ++ this._overlayKeyId == 0; ++ } ++}); +-- +2.21.0 + + +From 5d82db41ac53a1c7462e1ee69b155588b3e321fc Mon Sep 17 00:00:00 2001 +From: Jakub Steiner +Date: Mon, 15 Jul 2019 23:03:41 +0200 +Subject: [PATCH 09/30] classic: Update window-list styling + +Make buttons flatter, rounder to match default styling. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/82 +--- + extensions/window-list/classic.css | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) + +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index c506bea..cc967e0 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -4,21 +4,18 @@ + border-top-width: 1px; + border-bottom-width: 0px; + height: 2.25em ; ++ padding: 2px; + } + + .bottom-panel .window-button > StWidget, + .bottom-panel .window-picker-toggle > StWidget { +- background-gradient-drection: vertical; +- background-color: #fff; +- background-gradient-start: #fff; +- background-gradient-end: #eee; +- color: #000; + color: #2e3436; + background-color: #eee; +- border-radius: 2px; ++ border-radius: 3px; + padding: 3px 6px 1px; +- box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5); +- text-shadow: 0 0 transparent; ++ box-shadow: none; ++ text-shadow: none; ++ border: 1px solid rgba(0,0,0,0.2); + } + + .bottom-panel .window-button > StWidget { +@@ -26,10 +23,6 @@ + max-width: 18.75em; + } + +- .bottom-panel .window-picker-toggle > StWidet { +- border: 1px solid rgba(0,0,0,0.3); +- } +- + .bottom-panel .window-button:hover > StWidget, + .bottom-panel .window-picker-toggle:hover > StWidget { + background-color: #f9f9f9; +@@ -37,13 +30,13 @@ + + .bottom-panel .window-button:active > StWidget, + .bottom-panel .window-button:focus > StWidget { +- box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5); ++ box-shadow: inset 0 1px 3px rgba(0,0,0,0.1); + } + + .bottom-panel .window-button.focused > StWidget, + .bottom-panel .window-picker-toggle:checked > StWidget { +- background-color: #ddd; +- box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5); ++ background-color: #ccc; ++ box-shadow: inset 0 1px 3px rgba(0,0,0,0.1); + } + + .bottom-panel .window-button.focused:hover > StWidget { +@@ -52,5 +45,5 @@ + + .bottom-panel .window-button.minimized > StWidget { + color: #888; +- box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5); ++ box-shadow: none; + } +-- +2.21.0 + + +From 479a8907063970fb6f7e08cea9a2cd6f2e518b84 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 00:23:13 +0000 +Subject: [PATCH 10/30] window-list: Split out workspaceIndicator + +The extension has grown unwieldily big, so before starting to improve +on the workspace indicator, move it to its own source file. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/extension.js | 130 +----------------- + extensions/window-list/meson.build | 2 +- + extensions/window-list/workspaceIndicator.js | 135 +++++++++++++++++++ + 3 files changed, 138 insertions(+), 129 deletions(-) + create mode 100644 extensions/window-list/workspaceIndicator.js + +diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js +index b2784b4..1f854aa 100644 +--- a/extensions/window-list/extension.js ++++ b/extensions/window-list/extension.js +@@ -1,16 +1,16 @@ + /* exported init */ +-const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi; ++const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi; + + const DND = imports.ui.dnd; + const Main = imports.ui.main; + const Overview = imports.ui.overview; +-const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; + const Tweener = imports.ui.tweener; + + const ExtensionUtils = imports.misc.extensionUtils; + const Me = ExtensionUtils.getCurrentExtension(); + const { WindowPicker, WindowPickerToggle } = Me.imports.windowPicker; ++const { WorkspaceIndicator } = Me.imports.workspaceIndicator; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; +@@ -647,132 +647,6 @@ class AppButton extends BaseButton { + } + + +-let WorkspaceIndicator = GObject.registerClass( +-class WorkspaceIndicator extends PanelMenu.Button { +- _init() { +- super._init(0.0, _('Workspace Indicator'), true); +- this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); +- this.add_style_class_name('window-list-workspace-indicator'); +- this.menu.actor.remove_style_class_name('panel-menu'); +- +- let container = new St.Widget({ +- layout_manager: new Clutter.BinLayout(), +- x_expand: true, +- y_expand: true +- }); +- this.add_actor(container); +- +- let workspaceManager = global.workspace_manager; +- +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); +- this.statusLabel = new St.Label({ +- text: this._getStatusText(), +- x_align: Clutter.ActorAlign.CENTER, +- y_align: Clutter.ActorAlign.CENTER +- }); +- container.add_actor(this.statusLabel); +- +- this.workspacesItems = []; +- +- this._workspaceManagerSignals = []; +- this._workspaceManagerSignals.push(workspaceManager.connect('notify::n-workspaces', +- this._updateMenu.bind(this))); +- this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched', +- this._updateIndicator.bind(this))); +- +- this.connect('scroll-event', this._onScrollEvent.bind(this)); +- this._updateMenu(); +- +- this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); +- this._settingsChangedId = +- this._settings.connect('changed::workspace-names', +- this._updateMenu.bind(this)); +- } +- +- _onDestroy() { +- for (let i = 0; i < this._workspaceManagerSignals.length; i++) +- global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); +- +- if (this._settingsChangedId) { +- this._settings.disconnect(this._settingsChangedId); +- this._settingsChangedId = 0; +- } +- +- super._onDestroy(); +- } +- +- _updateIndicator() { +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); +- +- this.statusLabel.set_text(this._getStatusText()); +- } +- +- _getStatusText() { +- let workspaceManager = global.workspace_manager; +- let current = workspaceManager.get_active_workspace().index(); +- let total = workspaceManager.n_workspaces; +- +- return '%d / %d'.format(current + 1, total); +- } +- +- _updateMenu() { +- let workspaceManager = global.workspace_manager; +- +- this.menu.removeAll(); +- this.workspacesItems = []; +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); +- +- for (let i = 0; i < workspaceManager.n_workspaces; i++) { +- let name = Meta.prefs_get_workspace_name(i); +- let item = new PopupMenu.PopupMenuItem(name); +- item.workspaceId = i; +- +- item.connect('activate', (item, _event) => { +- this._activate(item.workspaceId); +- }); +- +- if (i == this._currentWorkspace) +- item.setOrnament(PopupMenu.Ornament.DOT); +- +- this.menu.addMenuItem(item); +- this.workspacesItems[i] = item; +- } +- +- this.statusLabel.set_text(this._getStatusText()); +- } +- +- _activate(index) { +- let workspaceManager = global.workspace_manager; +- +- if (index >= 0 && index < workspaceManager.n_workspaces) { +- let metaWorkspace = workspaceManager.get_workspace_by_index(index); +- metaWorkspace.activate(global.get_current_time()); +- } +- } +- +- _onScrollEvent(actor, event) { +- let direction = event.get_scroll_direction(); +- let diff = 0; +- if (direction == Clutter.ScrollDirection.DOWN) { +- diff = 1; +- } else if (direction == Clutter.ScrollDirection.UP) { +- diff = -1; +- } else { +- return; +- } +- +- let newIndex = this._currentWorkspace + diff; +- this._activate(newIndex); +- } +- +- _allocate(actor, box, flags) { +- if (actor.get_n_children() > 0) +- actor.get_first_child().allocate(box, flags); +- } +-}); +- + class WindowList { + constructor(perMonitor, monitor) { + this._perMonitor = perMonitor; +diff --git a/extensions/window-list/meson.build b/extensions/window-list/meson.build +index 5b1f5f5..34d7c3f 100644 +--- a/extensions/window-list/meson.build ++++ b/extensions/window-list/meson.build +@@ -4,7 +4,7 @@ extension_data += configure_file( + configuration: metadata_conf + ) + +-extension_sources += files('prefs.js', 'windowPicker.js') ++extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js') + extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml') + + if classic_mode_enabled +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +new file mode 100644 +index 0000000..fb3ffe7 +--- /dev/null ++++ b/extensions/window-list/workspaceIndicator.js +@@ -0,0 +1,135 @@ ++/* exported WorkspaceIndicator */ ++const { Clutter, Gio, GObject, Meta, St } = imports.gi; ++ ++const PanelMenu = imports.ui.panelMenu; ++const PopupMenu = imports.ui.popupMenu; ++ ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++ ++var WorkspaceIndicator = GObject.registerClass( ++class WorkspaceIndicator extends PanelMenu.Button { ++ _init() { ++ super._init(0.0, _('Workspace Indicator'), true); ++ this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); ++ this.add_style_class_name('window-list-workspace-indicator'); ++ this.menu.actor.remove_style_class_name('panel-menu'); ++ ++ let container = new St.Widget({ ++ layout_manager: new Clutter.BinLayout(), ++ x_expand: true, ++ y_expand: true ++ }); ++ this.add_actor(container); ++ ++ let workspaceManager = global.workspace_manager; ++ ++ this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this.statusLabel = new St.Label({ ++ text: this._getStatusText(), ++ x_align: Clutter.ActorAlign.CENTER, ++ y_align: Clutter.ActorAlign.CENTER ++ }); ++ container.add_actor(this.statusLabel); ++ ++ this.workspacesItems = []; ++ ++ this._workspaceManagerSignals = [ ++ workspaceManager.connect('notify::n-workspaces', ++ this._updateMenu.bind(this)), ++ workspaceManager.connect_after('workspace-switched', ++ this._updateIndicator.bind(this)) ++ ]; ++ ++ this.connect('scroll-event', this._onScrollEvent.bind(this)); ++ this._updateMenu(); ++ ++ this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); ++ this._settingsChangedId = this._settings.connect( ++ 'changed::workspace-names', this._updateMenu.bind(this)); ++ } ++ ++ _onDestroy() { ++ for (let i = 0; i < this._workspaceManagerSignals.length; i++) ++ global.workspace_manager.disconnect(this._workspaceManagerSignals[i]); ++ ++ if (this._settingsChangedId) { ++ this._settings.disconnect(this._settingsChangedId); ++ this._settingsChangedId = 0; ++ } ++ ++ super._onDestroy(); ++ } ++ ++ _updateIndicator() { ++ this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); ++ this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); ++ this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ ++ this.statusLabel.set_text(this._getStatusText()); ++ } ++ ++ _getStatusText() { ++ let workspaceManager = global.workspace_manager; ++ let current = workspaceManager.get_active_workspace().index(); ++ let total = workspaceManager.n_workspaces; ++ ++ return '%d / %d'.format(current + 1, total); ++ } ++ ++ _updateMenu() { ++ let workspaceManager = global.workspace_manager; ++ ++ this.menu.removeAll(); ++ this.workspacesItems = []; ++ this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ ++ for (let i = 0; i < workspaceManager.n_workspaces; i++) { ++ let name = Meta.prefs_get_workspace_name(i); ++ let item = new PopupMenu.PopupMenuItem(name); ++ item.workspaceId = i; ++ ++ item.connect('activate', (item, _event) => { ++ this._activate(item.workspaceId); ++ }); ++ ++ if (i == this._currentWorkspace) ++ item.setOrnament(PopupMenu.Ornament.DOT); ++ ++ this.menu.addMenuItem(item); ++ this.workspacesItems[i] = item; ++ } ++ ++ this.statusLabel.set_text(this._getStatusText()); ++ } ++ ++ _activate(index) { ++ let workspaceManager = global.workspace_manager; ++ ++ if (index >= 0 && index < workspaceManager.n_workspaces) { ++ let metaWorkspace = workspaceManager.get_workspace_by_index(index); ++ metaWorkspace.activate(global.get_current_time()); ++ } ++ } ++ ++ _onScrollEvent(actor, event) { ++ let direction = event.get_scroll_direction(); ++ let diff = 0; ++ if (direction == Clutter.ScrollDirection.DOWN) { ++ diff = 1; ++ } else if (direction == Clutter.ScrollDirection.UP) { ++ diff = -1; ++ } else { ++ return; ++ } ++ ++ let newIndex = this._currentWorkspace + diff; ++ this._activate(newIndex); ++ } ++ ++ _allocate(actor, box, flags) { ++ if (actor.get_n_children() > 0) ++ actor.get_first_child().allocate(box, flags); ++ } ++}); ++ +-- +2.21.0 + + +From 3380c9ca5c85a61101bf916a2b326c478d83475e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 17:39:53 +0000 +Subject: [PATCH 11/30] window-list: Use a more specific GTypeName for + workspace indicator + +Now that the class inherits from GObject, the generic name easily +conflicts with other classes otherwise, for example with the one +from the workspace-indicator extension. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index fb3ffe7..8ac43eb 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -7,8 +7,9 @@ const PopupMenu = imports.ui.popupMenu; + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + +-var WorkspaceIndicator = GObject.registerClass( +-class WorkspaceIndicator extends PanelMenu.Button { ++var WorkspaceIndicator = GObject.registerClass({ ++ GTypeName: 'WindowListWorkspaceIndicator' ++}, class WorkspaceIndicator extends PanelMenu.Button { + _init() { + super._init(0.0, _('Workspace Indicator'), true); + this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM)); +-- +2.21.0 + + +From ad21dfc00c53420794f940e8710b60d2dd25bb9e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 04:54:50 +0200 +Subject: [PATCH 12/30] window-list: Make some properties private + +There's no reason why they should be public. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 8ac43eb..7c0360a 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -26,14 +26,14 @@ var WorkspaceIndicator = GObject.registerClass({ + let workspaceManager = global.workspace_manager; + + this._currentWorkspace = workspaceManager.get_active_workspace().index(); +- this.statusLabel = new St.Label({ ++ this._statusLabel = new St.Label({ + text: this._getStatusText(), + x_align: Clutter.ActorAlign.CENTER, + y_align: Clutter.ActorAlign.CENTER + }); +- container.add_actor(this.statusLabel); ++ container.add_actor(this._statusLabel); + +- this.workspacesItems = []; ++ this._workspacesItems = []; + + this._workspaceManagerSignals = [ + workspaceManager.connect('notify::n-workspaces', +@@ -63,11 +63,11 @@ var WorkspaceIndicator = GObject.registerClass({ + } + + _updateIndicator() { +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); ++ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); + this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + +- this.statusLabel.set_text(this._getStatusText()); ++ this._statusLabel.set_text(this._getStatusText()); + } + + _getStatusText() { +@@ -82,7 +82,7 @@ var WorkspaceIndicator = GObject.registerClass({ + let workspaceManager = global.workspace_manager; + + this.menu.removeAll(); +- this.workspacesItems = []; ++ this._workspacesItems = []; + this._currentWorkspace = workspaceManager.get_active_workspace().index(); + + for (let i = 0; i < workspaceManager.n_workspaces; i++) { +@@ -98,10 +98,10 @@ var WorkspaceIndicator = GObject.registerClass({ + item.setOrnament(PopupMenu.Ornament.DOT); + + this.menu.addMenuItem(item); +- this.workspacesItems[i] = item; ++ this._workspacesItems[i] = item; + } + +- this.statusLabel.set_text(this._getStatusText()); ++ this._statusLabel.set_text(this._getStatusText()); + } + + _activate(index) { +-- +2.21.0 + + +From 14515b02845a6fe53c9a76eefc3359183dd8076f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 04:57:39 +0200 +Subject: [PATCH 13/30] window-list: Update workspace names in-place + +There's no good reason to rebuild the entire menu on workspace names +changes, we can simply update the labels in-place. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 7c0360a..9888838 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -47,7 +47,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); + this._settingsChangedId = this._settings.connect( +- 'changed::workspace-names', this._updateMenu.bind(this)); ++ 'changed::workspace-names', this._updateMenuLabels.bind(this)); + } + + _onDestroy() { +@@ -78,6 +78,14 @@ var WorkspaceIndicator = GObject.registerClass({ + return '%d / %d'.format(current + 1, total); + } + ++ _updateMenuLabels() { ++ for (let i = 0; i < this._workspacesItems.length; i++) { ++ let item = this._workspacesItems[i]; ++ let name = Meta.prefs_get_workspace_name(i); ++ item.label.text = name; ++ } ++ } ++ + _updateMenu() { + let workspaceManager = global.workspace_manager; + +-- +2.21.0 + + +From 7ecdd7d2c61694df8ca9f76016bd8113bfbd7b51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 04:59:19 +0200 +Subject: [PATCH 14/30] window-list: Minor cleanup + +Mutter has a dedicated method for getting the index of the active +workspace, use that instead of getting first the active workspace +and then its index. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 9888838..1f2e1c1 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -25,7 +25,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + let workspaceManager = global.workspace_manager; + +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + this._statusLabel = new St.Label({ + text: this._getStatusText(), + x_align: Clutter.ActorAlign.CENTER, +@@ -64,7 +64,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + _updateIndicator() { + this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); ++ this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); + this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + + this._statusLabel.set_text(this._getStatusText()); +@@ -72,7 +72,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + _getStatusText() { + let workspaceManager = global.workspace_manager; +- let current = workspaceManager.get_active_workspace().index(); ++ let current = workspaceManager.get_active_workspace_index(); + let total = workspaceManager.n_workspaces; + + return '%d / %d'.format(current + 1, total); +@@ -91,7 +91,7 @@ var WorkspaceIndicator = GObject.registerClass({ + + this.menu.removeAll(); + this._workspacesItems = []; +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + + for (let i = 0; i < workspaceManager.n_workspaces; i++) { + let name = Meta.prefs_get_workspace_name(i); +-- +2.21.0 + + +From 42ef09c097b297ee68207c4f439ec40e5998baa0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 05:11:34 +0200 +Subject: [PATCH 15/30] window-list: Improve workspace label styling + +The border currently looks off - it extends all the way vertically +and leaves zero spacing to the label horizontally. Fix both issues +by setting appropriate padding/margins. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/stylesheet.css | 8 +++----- + extensions/window-list/workspaceIndicator.js | 13 ++++++++----- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index 91383ab..bab8f76 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -85,13 +85,11 @@ + height: 24px; + } + +-.window-list-workspace-indicator { +- padding: 3px; +-} +- +-.window-list-workspace-indicator > StWidget { ++.window-list-workspace-indicator .status-label-bin { + background-color: rgba(200, 200, 200, .3); + border: 1px solid #cccccc; ++ padding: 0 3px; ++ margin: 3px 0; + } + + .notification { +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 1f2e1c1..598c516 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -26,12 +26,15 @@ var WorkspaceIndicator = GObject.registerClass({ + let workspaceManager = global.workspace_manager; + + this._currentWorkspace = workspaceManager.get_active_workspace_index(); +- this._statusLabel = new St.Label({ +- text: this._getStatusText(), +- x_align: Clutter.ActorAlign.CENTER, +- y_align: Clutter.ActorAlign.CENTER ++ this._statusLabel = new St.Label({ text: this._getStatusText() }); ++ ++ this._statusBin = new St.Bin({ ++ style_class: 'status-label-bin', ++ x_expand: true, ++ y_expand: true, ++ child: this._statusLabel + }); +- container.add_actor(this._statusLabel); ++ container.add_actor(this._statusBin); + + this._workspacesItems = []; + +-- +2.21.0 + + +From 0bf800b529ddfdc8663c63ff5fbf4ba5ac5d64d3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 05:08:31 +0200 +Subject: [PATCH 16/30] window-list: Refactor workspace signal handlers + +We are about to support a separate representation if horizontal +workspaces are used. To prepare for that, rename the handlers to +something more generic and split out menu-specific bits into a +dedicated help function. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/workspaceIndicator.js | 25 +++++++++++++++----- + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 598c516..78ca97e 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -40,9 +40,9 @@ var WorkspaceIndicator = GObject.registerClass({ + + this._workspaceManagerSignals = [ + workspaceManager.connect('notify::n-workspaces', +- this._updateMenu.bind(this)), ++ this._nWorkspacesChanged.bind(this)), + workspaceManager.connect_after('workspace-switched', +- this._updateIndicator.bind(this)) ++ this._onWorkspaceSwitched.bind(this)) + ]; + + this.connect('scroll-event', this._onScrollEvent.bind(this)); +@@ -65,14 +65,27 @@ var WorkspaceIndicator = GObject.registerClass({ + super._onDestroy(); + } + +- _updateIndicator() { +- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); +- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ _onWorkspaceSwitched() { ++ let workspaceManager = global.workspace_manager; ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); ++ ++ this._updateMenuOrnament(); + + this._statusLabel.set_text(this._getStatusText()); + } + ++ _nWorkspacesChanged() { ++ this._updateMenu(); ++ } ++ ++ _updateMenuOrnament() { ++ for (let i = 0; i < this._workspacesItems.length; i++) { ++ this._workspacesItems[i].setOrnament(i == this._currentWorkspace ++ ? PopupMenu.Ornament.DOT ++ : PopupMenu.Ornament.NONE); ++ } ++ } ++ + _getStatusText() { + let workspaceManager = global.workspace_manager; + let current = workspaceManager.get_active_workspace_index(); +-- +2.21.0 + + +From 263aeea7be1e5bd244664bb3aefd9b81d8a80e32 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 02:53:38 +0000 +Subject: [PATCH 17/30] window-list: Support horizontal workspace layout + +Unlike in GNOME 2, the workspace indicator we display in the window list +isn't a workspace switcher, but a menu button that allows switching +workspaces via its menu. The reason for that is that a horizontal +in-place switcher would be at odds with the vertical workspace layout +used in GNOME 3. + +However that reasoning doesn't apply when the layout is changed to a +horizontal one, so replace the button with a traditional workspace +switcher in that case. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70 +--- + extensions/window-list/classic.css | 9 +++ + extensions/window-list/stylesheet.css | 29 +++++++++ + extensions/window-list/workspaceIndicator.js | 66 +++++++++++++++++++- + 3 files changed, 103 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index cc967e0..c533473 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -47,3 +47,12 @@ + color: #888; + box-shadow: none; + } ++ ++/* workspace switcher */ ++.window-list-workspace-indicator .workspace { ++ background-color: #ddd; ++} ++ ++.window-list-workspace-indicator .workspace.active { ++ background-color: #ccc; ++} +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index bab8f76..ad5978a 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -92,6 +92,35 @@ + margin: 3px 0; + } + ++.window-list-workspace-indicator .workspaces-box { ++ spacing: 3px; ++ padding: 3px; ++} ++ ++.window-list-workspace-indicator .workspace { ++ border: 1px solid #cccccc; ++ width: 52px; ++} ++ ++.window-list-workspace-indicator .workspace:first-child:last-child:ltr, ++.window-list-workspace-indicator .workspace:first-child:last-child:rtl { ++ border-radius: 4px; ++} ++ ++.window-list-workspace-indicator .workspace:first-child:ltr, ++.window-list-workspace-indicator .workspace:last-child:rtl { ++ border-radius: 4px 0 0 4px; ++} ++ ++.window-list-workspace-indicator .workspace:first-child:rtl, ++.window-list-workspace-indicator .workspace:last-child:ltr { ++ border-radius: 0 4px 4px 0; ++} ++ ++.window-list-workspace-indicator .workspace.active { ++ background-color: rgba(200, 200, 200, .3); ++} ++ + .notification { + font-weight: normal; + } +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 78ca97e..1258ed2 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -7,6 +7,25 @@ const PopupMenu = imports.ui.popupMenu; + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + ++let WorkspaceThumbnail = GObject.registerClass({ ++ GTypeName: 'WindowListWorkspaceThumbnail' ++}, class WorkspaceThumbnail extends St.Button { ++ _init(index) { ++ super._init({ ++ style_class: 'workspace' ++ }); ++ ++ this._index = index; ++ } ++ ++ // eslint-disable-next-line camelcase ++ on_clicked() { ++ let ws = global.workspace_manager.get_workspace_by_index(this._index); ++ if (ws) ++ ws.activate(global.get_current_time()); ++ } ++}); ++ + var WorkspaceIndicator = GObject.registerClass({ + GTypeName: 'WindowListWorkspaceIndicator' + }, class WorkspaceIndicator extends PanelMenu.Button { +@@ -36,17 +55,30 @@ var WorkspaceIndicator = GObject.registerClass({ + }); + container.add_actor(this._statusBin); + ++ this._thumbnailsBox = new St.BoxLayout({ ++ style_class: 'workspaces-box', ++ y_expand: true, ++ reactive: true ++ }); ++ this._thumbnailsBox.connect('scroll-event', ++ this._onScrollEvent.bind(this)); ++ container.add_actor(this._thumbnailsBox); ++ + this._workspacesItems = []; + + this._workspaceManagerSignals = [ + workspaceManager.connect('notify::n-workspaces', + this._nWorkspacesChanged.bind(this)), + workspaceManager.connect_after('workspace-switched', +- this._onWorkspaceSwitched.bind(this)) ++ this._onWorkspaceSwitched.bind(this)), ++ workspaceManager.connect('notify::layout-rows', ++ this._onWorkspaceOrientationChanged.bind(this)) + ]; + + this.connect('scroll-event', this._onScrollEvent.bind(this)); + this._updateMenu(); ++ this._updateThumbnails(); ++ this._onWorkspaceOrientationChanged(); + + this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.wm.preferences' }); + this._settingsChangedId = this._settings.connect( +@@ -65,17 +97,27 @@ var WorkspaceIndicator = GObject.registerClass({ + super._onDestroy(); + } + ++ _onWorkspaceOrientationChanged() { ++ let vertical = global.workspace_manager.layout_rows == -1; ++ this.reactive = vertical; ++ ++ this._statusBin.visible = vertical; ++ this._thumbnailsBox.visible = !vertical; ++ } ++ + _onWorkspaceSwitched() { + let workspaceManager = global.workspace_manager; + this._currentWorkspace = workspaceManager.get_active_workspace_index(); + + this._updateMenuOrnament(); ++ this._updateActiveThumbnail(); + + this._statusLabel.set_text(this._getStatusText()); + } + + _nWorkspacesChanged() { + this._updateMenu(); ++ this._updateThumbnails(); + } + + _updateMenuOrnament() { +@@ -86,6 +128,16 @@ var WorkspaceIndicator = GObject.registerClass({ + } + } + ++ _updateActiveThumbnail() { ++ let thumbs = this._thumbnailsBox.get_children(); ++ for (let i = 0; i < thumbs.length; i++) { ++ if (i == this._currentWorkspace) ++ thumbs[i].add_style_class_name('active'); ++ else ++ thumbs[i].remove_style_class_name('active'); ++ } ++ } ++ + _getStatusText() { + let workspaceManager = global.workspace_manager; + let current = workspaceManager.get_active_workspace_index(); +@@ -128,6 +180,18 @@ var WorkspaceIndicator = GObject.registerClass({ + this._statusLabel.set_text(this._getStatusText()); + } + ++ _updateThumbnails() { ++ let workspaceManager = global.workspace_manager; ++ ++ this._thumbnailsBox.destroy_all_children(); ++ ++ for (let i = 0; i < workspaceManager.n_workspaces; i++) { ++ let thumb = new WorkspaceThumbnail(i); ++ this._thumbnailsBox.add_actor(thumb); ++ } ++ this._updateActiveThumbnail(); ++ } ++ + _activate(index) { + let workspaceManager = global.workspace_manager; + +-- +2.21.0 + + +From 2a2958831f51968089262b1e41bc908a69ef6834 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 5 Jun 2019 03:31:16 +0000 +Subject: [PATCH 18/30] classic: Add 'horizontal-workspaces' extension + +Vertical workspaces are another defining characteristics of GNOME 3, +and thus rather un-classic. That switch was driven by the overall +layout of the overview, and now that we disable the overview in +GNOME Classic, we can just return to the traditional workspace +layout as well. + +Add a small extension that does just that. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/72 +--- + extensions/horizontal-workspaces/extension.js | 18 ++++++++++++++++++ + extensions/horizontal-workspaces/meson.build | 5 +++++ + .../horizontal-workspaces/metadata.json.in | 10 ++++++++++ + .../horizontal-workspaces/stylesheet.css | 1 + + meson.build | 1 + + 5 files changed, 35 insertions(+) + create mode 100644 extensions/horizontal-workspaces/extension.js + create mode 100644 extensions/horizontal-workspaces/meson.build + create mode 100644 extensions/horizontal-workspaces/metadata.json.in + create mode 100644 extensions/horizontal-workspaces/stylesheet.css + +diff --git a/extensions/horizontal-workspaces/extension.js b/extensions/horizontal-workspaces/extension.js +new file mode 100644 +index 0000000..b3937ce +--- /dev/null ++++ b/extensions/horizontal-workspaces/extension.js +@@ -0,0 +1,18 @@ ++/* exported enable disable */ ++const { Meta } = imports.gi; ++ ++function enable() { ++ global.workspace_manager.override_workspace_layout( ++ Meta.DisplayCorner.TOPLEFT, ++ false, ++ 1, ++ -1); ++} ++ ++function disable() { ++ global.workspace_manager.override_workspace_layout( ++ Meta.DisplayCorner.TOPLEFT, ++ false, ++ -1, ++ 1); ++} +diff --git a/extensions/horizontal-workspaces/meson.build b/extensions/horizontal-workspaces/meson.build +new file mode 100644 +index 0000000..48504f6 +--- /dev/null ++++ b/extensions/horizontal-workspaces/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/horizontal-workspaces/metadata.json.in b/extensions/horizontal-workspaces/metadata.json.in +new file mode 100644 +index 0000000..f109e06 +--- /dev/null ++++ b/extensions/horizontal-workspaces/metadata.json.in +@@ -0,0 +1,10 @@ ++{ ++"extension-id": "@extension_id@", ++"uuid": "@uuid@", ++"settings-schema": "@gschemaname@", ++"gettext-domain": "@gettext_domain@", ++"name": "Horizontal workspaces", ++"description": "Use a horizontal workspace layout", ++"shell-version": [ "@shell_current@" ], ++"url": "@url@" ++} +diff --git a/extensions/horizontal-workspaces/stylesheet.css b/extensions/horizontal-workspaces/stylesheet.css +new file mode 100644 +index 0000000..25134b6 +--- /dev/null ++++ b/extensions/horizontal-workspaces/stylesheet.css +@@ -0,0 +1 @@ ++/* This extensions requires no special styling */ +diff --git a/meson.build b/meson.build +index 32743ed..23bd5ad 100644 +--- a/meson.build ++++ b/meson.build +@@ -34,6 +34,7 @@ uuid_suffix = '@gnome-shell-extensions.gcampax.github.com' + classic_extensions = [ + 'apps-menu', + 'desktop-icons', ++ 'horizontal-workspaces', + 'places-menu', + 'launch-new-instance', + 'top-icons', +-- +2.21.0 + + +From 6a7b057028a1e4264312974d3ca21e16f5c07776 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 11 Jun 2019 23:01:20 +0000 +Subject: [PATCH 19/30] window-list: Turn workspace thumbs into drop targets + +It makes some sense to allow using the workspace indicator for moving +windows between workspaces as well as for workspace switching. This +applies particularly in GNOME classic after we disabled the overview +there, so that there is again a non-shortcut way of moving windows +between workspaces. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74 +--- + extensions/window-list/workspaceIndicator.js | 27 ++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 1258ed2..4831768 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -1,6 +1,8 @@ + /* exported WorkspaceIndicator */ + const { Clutter, Gio, GObject, Meta, St } = imports.gi; + ++const DND = imports.ui.dnd; ++const Main = imports.ui.main; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; + +@@ -16,6 +18,31 @@ let WorkspaceThumbnail = GObject.registerClass({ + }); + + this._index = index; ++ this._delegate = this; // needed for DND ++ } ++ ++ acceptDrop(source) { ++ if (!source.realWindow) ++ return false; ++ ++ let window = source.realWindow.get_meta_window(); ++ this._moveWindow(window); ++ return true; ++ } ++ ++ handleDragOver(source) { ++ if (source.realWindow) ++ return DND.DragMotionResult.MOVE_DROP; ++ else ++ return DND.DragMotionResult.CONTINUE; ++ } ++ ++ ++ _moveWindow(window) { ++ let monitorIndex = Main.layoutManager.findIndexForActor(this); ++ if (monitorIndex != window.get_monitor()) ++ window.move_to_monitor(monitorIndex); ++ window.change_workspace_by_index(this._index, false); + } + + // eslint-disable-next-line camelcase +-- +2.21.0 + + +From 7dca894705ddfd73016f4d073f6fe486563ce324 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 26 Jun 2019 23:55:58 +0000 +Subject: [PATCH 20/30] window-list: Show previews in workspace switcher + +Currently the new horizontal workspace switcher only shows a series of +buttons, with no indication of the workspaces' contents. Go full GNOME 2 +and add tiny draggable preview rectangles that represent the windows +on a particular workspace. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74 +--- + extensions/window-list/classic.css | 10 ++ + extensions/window-list/stylesheet.css | 10 ++ + extensions/window-list/workspaceIndicator.js | 154 ++++++++++++++++++- + 3 files changed, 173 insertions(+), 1 deletion(-) + +diff --git a/extensions/window-list/classic.css b/extensions/window-list/classic.css +index c533473..7079d3e 100644 +--- a/extensions/window-list/classic.css ++++ b/extensions/window-list/classic.css +@@ -56,3 +56,13 @@ + .window-list-workspace-indicator .workspace.active { + background-color: #ccc; + } ++ ++.window-list-window-preview { ++ background-color: #ededed; ++ border: 1px solid #ccc; ++} ++ ++.window-list-window-preview.active { ++ background-color: #f6f5f4; ++ border: 2px solid #888; ++} +diff --git a/extensions/window-list/stylesheet.css b/extensions/window-list/stylesheet.css +index ad5978a..79d56ba 100644 +--- a/extensions/window-list/stylesheet.css ++++ b/extensions/window-list/stylesheet.css +@@ -121,6 +121,16 @@ + background-color: rgba(200, 200, 200, .3); + } + ++.window-list-window-preview { ++ background-color: #252525; ++ border: 1px solid #ccc; ++} ++ ++.window-list-window-preview.active { ++ background-color: #353535; ++ border: 2px solid #ccc; ++} ++ + .notification { + font-weight: normal; + } +diff --git a/extensions/window-list/workspaceIndicator.js b/extensions/window-list/workspaceIndicator.js +index 4831768..ca47611 100644 +--- a/extensions/window-list/workspaceIndicator.js ++++ b/extensions/window-list/workspaceIndicator.js +@@ -9,16 +9,131 @@ const PopupMenu = imports.ui.popupMenu; + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + ++let WindowPreview = GObject.registerClass({ ++ GTypeName: 'WindowListWindowPreview' ++}, class WindowPreview extends St.Button { ++ _init(window) { ++ super._init({ ++ style_class: 'window-list-window-preview' ++ }); ++ ++ this._delegate = this; ++ DND.makeDraggable(this, { restoreOnSuccess: true }); ++ ++ this._window = window; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ ++ this._sizeChangedId = this._window.connect('size-changed', ++ this._relayout.bind(this)); ++ this._positionChangedId = this._window.connect('position-changed', ++ this._relayout.bind(this)); ++ this._minimizedChangedId = this._window.connect('notify::minimized', ++ this._relayout.bind(this)); ++ this._monitorEnteredId = global.display.connect('window-entered-monitor', ++ this._relayout.bind(this)); ++ this._monitorLeftId = global.display.connect('window-left-monitor', ++ this._relayout.bind(this)); ++ ++ // Do initial layout when we get a parent ++ let id = this.connect('parent-set', () => { ++ this.disconnect(id); ++ if (!this.get_parent()) ++ return; ++ this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ this._laterId = 0; ++ this._relayout(); ++ return false; ++ }); ++ }); ++ ++ this._focusChangedId = global.display.connect('notify::focus-window', ++ this._onFocusChanged.bind(this)); ++ this._onFocusChanged(); ++ } ++ ++ // needed for DND ++ get realWindow() { ++ return this._window.get_compositor_private(); ++ } ++ ++ _onDestroy() { ++ this._window.disconnect(this._sizeChangedId); ++ this._window.disconnect(this._positionChangedId); ++ this._window.disconnect(this._minimizedChangedId); ++ global.display.disconnect(this._monitorEnteredId); ++ global.display.disconnect(this._monitorLeftId); ++ global.display.disconnect(this._focusChangedId); ++ if (this._laterId) ++ Meta.later_remove(this._laterId); ++ } ++ ++ _onFocusChanged() { ++ if (global.display.focus_window == this._window) ++ this.add_style_class_name('active'); ++ else ++ this.remove_style_class_name('active'); ++ } ++ ++ _relayout() { ++ let monitor = Main.layoutManager.findIndexForActor(this); ++ this.visible = monitor == this._window.get_monitor() && ++ this._window.showing_on_its_workspace(); ++ ++ if (!this.visible) ++ return; ++ ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor); ++ let hscale = this.get_parent().allocation.get_width() / workArea.width; ++ let vscale = this.get_parent().allocation.get_height() / workArea.height; ++ ++ let frameRect = this._window.get_frame_rect(); ++ this.set_size( ++ Math.round(Math.min(frameRect.width, workArea.width) * hscale), ++ Math.round(Math.min(frameRect.height, workArea.height) * vscale)); ++ this.set_position( ++ Math.round(frameRect.x * hscale), ++ Math.round(frameRect.y * vscale)); ++ } ++}); ++ + let WorkspaceThumbnail = GObject.registerClass({ + GTypeName: 'WindowListWorkspaceThumbnail' + }, class WorkspaceThumbnail extends St.Button { + _init(index) { + super._init({ +- style_class: 'workspace' ++ style_class: 'workspace', ++ child: new Clutter.Actor({ ++ layout_manager: new Clutter.BinLayout(), ++ clip_to_allocation: true ++ }), ++ x_fill: true, ++ y_fill: true + }); + ++ this.connect('destroy', this._onDestroy.bind(this)); ++ + this._index = index; + this._delegate = this; // needed for DND ++ ++ this._windowPreviews = new Map(); ++ ++ let workspaceManager = global.workspace_manager; ++ this._workspace = workspaceManager.get_workspace_by_index(index); ++ ++ this._windowAddedId = this._workspace.connect('window-added', ++ (ws, window) => { ++ this._addWindow(window); ++ }); ++ this._windowRemovedId = this._workspace.connect('window-removed', ++ (ws, window) => { ++ this._removeWindow(window); ++ }); ++ this._restackedId = global.display.connect('restacked', ++ this._onRestacked.bind(this)); ++ ++ this._workspace.list_windows().forEach(w => this._addWindow(w)); ++ this._onRestacked(); + } + + acceptDrop(source) { +@@ -37,6 +152,37 @@ let WorkspaceThumbnail = GObject.registerClass({ + return DND.DragMotionResult.CONTINUE; + } + ++ _addWindow(window) { ++ if (this._windowPreviews.has(window)) ++ return; ++ ++ let preview = new WindowPreview(window); ++ preview.connect('clicked', (a, btn) => this.emit('clicked', btn)); ++ this._windowPreviews.set(window, preview); ++ this.child.add_child(preview); ++ } ++ ++ _removeWindow(window) { ++ let preview = this._windowPreviews.get(window); ++ if (!preview) ++ return; ++ ++ this._windowPreviews.delete(window); ++ preview.destroy(); ++ } ++ ++ _onRestacked() { ++ let lastPreview = null; ++ let windows = global.get_window_actors().map(a => a.meta_window); ++ for (let i = 0; i < windows.length; i++) { ++ let preview = this._windowPreviews.get(windows[i]); ++ if (!preview) ++ continue; ++ ++ this.child.set_child_above_sibling(preview, lastPreview); ++ lastPreview = preview; ++ } ++ } + + _moveWindow(window) { + let monitorIndex = Main.layoutManager.findIndexForActor(this); +@@ -51,6 +197,12 @@ let WorkspaceThumbnail = GObject.registerClass({ + if (ws) + ws.activate(global.get_current_time()); + } ++ ++ _onDestroy() { ++ this._workspace.disconnect(this._windowAddedId); ++ this._workspace.disconnect(this._windowRemovedId); ++ global.display.disconnect(this._restackedId); ++ } + }); + + var WorkspaceIndicator = GObject.registerClass({ +-- +2.21.0 + + +From 77b9d4fee20d84816cb64bfa6b95fddd589b4788 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sat, 29 Jun 2019 01:24:54 +0200 +Subject: [PATCH 21/30] workspace-indicator: Fix whitespace error + +We only want a single space before and after operators, not at least +one. Unfortunately eslint only enforces the latter ... + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 3be1268..c3c4d5f 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -109,7 +109,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + _activate(index) { + let workspaceManager = global.workspace_manager; + +- if (index >= 0 && index < workspaceManager.n_workspaces) { ++ if (index >= 0 && index < workspaceManager.n_workspaces) { + let metaWorkspace = workspaceManager.get_workspace_by_index(index); + metaWorkspace.activate(global.get_current_time()); + } +-- +2.21.0 + + +From a68ef2096fed7580f7177991e354910add1ab79c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 9 Jun 2019 22:58:29 +0000 +Subject: [PATCH 22/30] workspace-indicator: Make some properties private + +There's no reason why they should be public. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 30 ++++++++++----------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index c3c4d5f..e052181 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -23,14 +23,14 @@ class WorkspaceIndicator extends PanelMenu.Button { + let workspaceManager = global.workspace_manager; + + this._currentWorkspace = workspaceManager.get_active_workspace().index(); +- this.statusLabel = new St.Label({ ++ this._statusLabel = new St.Label({ + y_align: Clutter.ActorAlign.CENTER, + text: this._labelText() + }); + +- this.add_actor(this.statusLabel); ++ this.add_actor(this._statusLabel); + +- this.workspacesItems = []; ++ this._workspacesItems = []; + this._workspaceSection = new PopupMenu.PopupMenuSection(); + this.menu.addMenuItem(this._workspaceSection); + +@@ -46,7 +46,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + this._createWorkspacesSection(); + + //styling +- this.statusLabel.add_style_class_name('panel-workspace-indicator'); ++ this._statusLabel.add_style_class_name('panel-workspace-indicator'); + + this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA }); + this._settingsChangedId = +@@ -67,11 +67,11 @@ class WorkspaceIndicator extends PanelMenu.Button { + } + + _updateIndicator() { +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); ++ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); + this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); +- this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + +- this.statusLabel.set_text(this._labelText()); ++ this._statusLabel.set_text(this._labelText()); + } + + _labelText(workspaceIndex) { +@@ -86,24 +86,24 @@ class WorkspaceIndicator extends PanelMenu.Button { + let workspaceManager = global.workspace_manager; + + this._workspaceSection.removeAll(); +- this.workspacesItems = []; ++ this._workspacesItems = []; + this._currentWorkspace = workspaceManager.get_active_workspace().index(); + + let i = 0; + for (; i < workspaceManager.n_workspaces; i++) { +- this.workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i)); +- this._workspaceSection.addMenuItem(this.workspacesItems[i]); +- this.workspacesItems[i].workspaceId = i; +- this.workspacesItems[i].label_actor = this.statusLabel; +- this.workspacesItems[i].connect('activate', (actor, _event) => { ++ this._workspacesItems[i] = new PopupMenu.PopupMenuItem(this._labelText(i)); ++ this._workspaceSection.addMenuItem(this._workspacesItems[i]); ++ this._workspacesItems[i].workspaceId = i; ++ this._workspacesItems[i].label_actor = this._statusLabel; ++ this._workspacesItems[i].connect('activate', (actor, _event) => { + this._activate(actor.workspaceId); + }); + + if (i == this._currentWorkspace) +- this.workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT); ++ this._workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT); + } + +- this.statusLabel.set_text(this._labelText()); ++ this._statusLabel.set_text(this._labelText()); + } + + _activate(index) { +-- +2.21.0 + + +From 7e74dd6e331846564898ed220d58eb54cad83524 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 9 Jun 2019 23:03:55 +0000 +Subject: [PATCH 23/30] workspace-indicator: Update workspace names in-place + +There's no good reason to rebuild the entire menu on workspace names +changes, we can simply update the labels in-place. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index e052181..205ee36 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -49,9 +49,9 @@ class WorkspaceIndicator extends PanelMenu.Button { + this._statusLabel.add_style_class_name('panel-workspace-indicator'); + + this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA }); +- this._settingsChangedId = +- this._settings.connect(`changed::${WORKSPACE_KEY}`, +- this._createWorkspacesSection.bind(this)); ++ this._settingsChangedId = this._settings.connect( ++ `changed::${WORKSPACE_KEY}`, ++ this._updateMenuLabels.bind(this)); + } + + _onDestroy() { +@@ -82,6 +82,11 @@ class WorkspaceIndicator extends PanelMenu.Button { + return Meta.prefs_get_workspace_name(workspaceIndex); + } + ++ _updateMenuLabels() { ++ for (let i = 0; i < this._workspacesItems.length; i++) ++ this._workspacesItems[i].label.text = this._labelText(i); ++ } ++ + _createWorkspacesSection() { + let workspaceManager = global.workspace_manager; + +-- +2.21.0 + + +From dfcd296cf33de8a3e739c340734332a63f2c01f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 9 Jun 2019 23:05:00 +0000 +Subject: [PATCH 24/30] workspace-indicator: Minor cleanup + +Mutter has a dedicated method for getting the index of the active +workspace, use that instead of getting first the active workspace +and then its index. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 205ee36..7ebc1f0 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -22,7 +22,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + + let workspaceManager = global.workspace_manager; + +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + this._statusLabel = new St.Label({ + y_align: Clutter.ActorAlign.CENTER, + text: this._labelText() +@@ -68,7 +68,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + + _updateIndicator() { + this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); +- this._currentWorkspace = global.workspace_manager.get_active_workspace().index(); ++ this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); + this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); + + this._statusLabel.set_text(this._labelText()); +@@ -92,7 +92,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + + this._workspaceSection.removeAll(); + this._workspacesItems = []; +- this._currentWorkspace = workspaceManager.get_active_workspace().index(); ++ this._currentWorkspace = workspaceManager.get_active_workspace_index(); + + let i = 0; + for (; i < workspaceManager.n_workspaces; i++) { +@@ -131,7 +131,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + return; + } + +- let newIndex = global.workspace_manager.get_active_workspace().index() + diff; ++ let newIndex = global.workspace_manager.get_active_workspace_index() + diff; + this._activate(newIndex); + } + }); +-- +2.21.0 + + +From 00d1e9637f0b7f51b271c384fb55ecaea673bb70 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 9 Jun 2019 23:09:12 +0000 +Subject: [PATCH 25/30] workspace-indicator: Refactor workspace signal handlers + +We are about to support a separate representation if horizontal +workspaces are used. To prepare for that, rename the handlers to +something more generic and split out menu-specific bits into a +dedicated help function. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 31 ++++++++++++++------- + 1 file changed, 21 insertions(+), 10 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 7ebc1f0..34fc275 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -34,13 +34,12 @@ class WorkspaceIndicator extends PanelMenu.Button { + this._workspaceSection = new PopupMenu.PopupMenuSection(); + this.menu.addMenuItem(this._workspaceSection); + +- this._workspaceManagerSignals = []; +- this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-added', +- this._createWorkspacesSection.bind(this))); +- this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-removed', +- this._createWorkspacesSection.bind(this))); +- this._workspaceManagerSignals.push(workspaceManager.connect_after('workspace-switched', +- this._updateIndicator.bind(this))); ++ this._workspaceManagerSignals = [ ++ workspaceManager.connect_after('notify::n-workspaces', ++ this._nWorkspacesChanged.bind(this)), ++ workspaceManager.connect_after('workspace-switched', ++ this._onWorkspaceSwitched.bind(this)) ++ ]; + + this.connect('scroll-event', this._onScrollEvent.bind(this)); + this._createWorkspacesSection(); +@@ -66,14 +65,26 @@ class WorkspaceIndicator extends PanelMenu.Button { + super._onDestroy(); + } + +- _updateIndicator() { +- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE); ++ _onWorkspaceSwitched() { + this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); +- this._workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT); ++ ++ this._updateMenuOrnament(); + + this._statusLabel.set_text(this._labelText()); + } + ++ _nWorkspacesChanged() { ++ this._createWorkspacesSection(); ++ } ++ ++ _updateMenuOrnament() { ++ for (let i = 0; i < this._workspacesItems.length; i++) { ++ this._workspacesItems[i].setOrnament(i == this._currentWorkspace ++ ? PopupMenu.Ornament.DOT ++ : PopupMenu.Ornament.NONE); ++ } ++ } ++ + _labelText(workspaceIndex) { + if (workspaceIndex == undefined) { + workspaceIndex = this._currentWorkspace; +-- +2.21.0 + + +From 0834d04691de28f3a216578e55335c6e9b3e4fad Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 9 Jun 2019 23:17:35 +0000 +Subject: [PATCH 26/30] workspace-indicator: Minor cleanup + +Pass the style class at construction time instead of setting it later. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 34fc275..672b98d 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -24,6 +24,7 @@ class WorkspaceIndicator extends PanelMenu.Button { + + this._currentWorkspace = workspaceManager.get_active_workspace_index(); + this._statusLabel = new St.Label({ ++ style_class: 'panel-workspace-indicator', + y_align: Clutter.ActorAlign.CENTER, + text: this._labelText() + }); +@@ -44,9 +45,6 @@ class WorkspaceIndicator extends PanelMenu.Button { + this.connect('scroll-event', this._onScrollEvent.bind(this)); + this._createWorkspacesSection(); + +- //styling +- this._statusLabel.add_style_class_name('panel-workspace-indicator'); +- + this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA }); + this._settingsChangedId = this._settings.connect( + `changed::${WORKSPACE_KEY}`, +-- +2.21.0 + + +From 07fca6b1ee27a1eaf97027e4353ab46ea9cb745e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Sun, 9 Jun 2019 23:45:24 +0000 +Subject: [PATCH 27/30] workspace-indicator: Support horizontal workspace + layout + +Just like we did for the workspace indicator in the window-list, improve +the handling of horizontal workspace layouts by showing the switcher +in-place instead of delegating the functionality to a menu. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71 +--- + extensions/workspace-indicator/extension.js | 76 ++++++++++++++++++- + extensions/workspace-indicator/stylesheet.css | 18 ++++- + 2 files changed, 90 insertions(+), 4 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 672b98d..48019da 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -15,11 +15,38 @@ const ExtensionUtils = imports.misc.extensionUtils; + const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; + const WORKSPACE_KEY = 'workspace-names'; + ++let WorkspaceThumbnail = GObject.registerClass({ ++ GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail' ++}, class WorkspaceThumbnail extends St.Button { ++ _init(index) { ++ super._init({ ++ style_class: 'workspace', ++ }); ++ ++ this._index = index; ++ } ++ ++ // eslint-disable-next-line camelcase ++ on_clicked() { ++ let ws = global.workspace_manager.get_workspace_by_index(this._index); ++ if (ws) ++ ws.activate(global.get_current_time()); ++ } ++}); ++ ++ + let WorkspaceIndicator = GObject.registerClass( + class WorkspaceIndicator extends PanelMenu.Button { + _init() { + super._init(0.0, _('Workspace Indicator')); + ++ let container = new St.Widget({ ++ layout_manager: new Clutter.BinLayout(), ++ x_expand: true, ++ y_expand: true ++ }); ++ this.add_actor(container); ++ + let workspaceManager = global.workspace_manager; + + this._currentWorkspace = workspaceManager.get_active_workspace_index(); +@@ -29,7 +56,15 @@ class WorkspaceIndicator extends PanelMenu.Button { + text: this._labelText() + }); + +- this.add_actor(this._statusLabel); ++ container.add_actor(this._statusLabel); ++ ++ this._thumbnailsBox = new St.BoxLayout({ ++ style_class: 'panel-workspace-indicator-box', ++ y_expand: true, ++ reactive: true ++ }); ++ ++ container.add_actor(this._thumbnailsBox); + + this._workspacesItems = []; + this._workspaceSection = new PopupMenu.PopupMenuSection(); +@@ -39,11 +74,16 @@ class WorkspaceIndicator extends PanelMenu.Button { + workspaceManager.connect_after('notify::n-workspaces', + this._nWorkspacesChanged.bind(this)), + workspaceManager.connect_after('workspace-switched', +- this._onWorkspaceSwitched.bind(this)) ++ this._onWorkspaceSwitched.bind(this)), ++ workspaceManager.connect('notify::layout-rows', ++ this._onWorkspaceOrientationChanged.bind(this)) + ]; + + this.connect('scroll-event', this._onScrollEvent.bind(this)); ++ this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this)); + this._createWorkspacesSection(); ++ this._updateThumbnails(); ++ this._onWorkspaceOrientationChanged(); + + this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA }); + this._settingsChangedId = this._settings.connect( +@@ -63,16 +103,26 @@ class WorkspaceIndicator extends PanelMenu.Button { + super._onDestroy(); + } + ++ _onWorkspaceOrientationChanged() { ++ let vertical = global.workspace_manager.layout_rows == -1; ++ this.reactive = vertical; ++ ++ this._statusLabel.visible = vertical; ++ this._thumbnailsBox.visible = !vertical; ++ } ++ + _onWorkspaceSwitched() { + this._currentWorkspace = global.workspace_manager.get_active_workspace_index(); + + this._updateMenuOrnament(); ++ this._updateActiveThumbnail(); + + this._statusLabel.set_text(this._labelText()); + } + + _nWorkspacesChanged() { + this._createWorkspacesSection(); ++ this._updateThumbnails(); + } + + _updateMenuOrnament() { +@@ -83,6 +133,16 @@ class WorkspaceIndicator extends PanelMenu.Button { + } + } + ++ _updateActiveThumbnail() { ++ let thumbs = this._thumbnailsBox.get_children(); ++ for (let i = 0; i < thumbs.length; i++) { ++ if (i == this._currentWorkspace) ++ thumbs[i].add_style_class_name('active'); ++ else ++ thumbs[i].remove_style_class_name('active'); ++ } ++ } ++ + _labelText(workspaceIndex) { + if (workspaceIndex == undefined) { + workspaceIndex = this._currentWorkspace; +@@ -120,6 +180,18 @@ class WorkspaceIndicator extends PanelMenu.Button { + this._statusLabel.set_text(this._labelText()); + } + ++ _updateThumbnails() { ++ let workspaceManager = global.workspace_manager; ++ ++ this._thumbnailsBox.destroy_all_children(); ++ ++ for (let i = 0; i < workspaceManager.n_workspaces; i++) { ++ let thumb = new WorkspaceThumbnail(i); ++ this._thumbnailsBox.add_actor(thumb); ++ } ++ this._updateActiveThumbnail(); ++ } ++ + _activate(index) { + let workspaceManager = global.workspace_manager; + +diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css +index 1271f1c..a15081e 100644 +--- a/extensions/workspace-indicator/stylesheet.css ++++ b/extensions/workspace-indicator/stylesheet.css +@@ -1,5 +1,19 @@ +-.panel-workspace-indicator { ++.panel-workspace-indicator, ++.panel-workspace-indicator-box .workspace { + padding: 0 8px; +- background-color: rgba(200, 200, 200, .5); + border: 1px solid #cccccc; + } ++ ++.panel-workspace-indicator, ++.panel-workspace-indicator-box .workspace.active { ++ background-color: rgba(200, 200, 200, .5); ++} ++ ++.panel-workspace-indicator-box .workspace { ++ background-color: rgba(200, 200, 200, .3); ++ border-left-width: 0; ++} ++ ++.panel-workspace-indicator-box .workspace:first-child { ++ border-left-width: 1px; ++} +-- +2.21.0 + + +From 58496daaf5591e86238d7ab7f470b5ad7797b3e3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 28 Jun 2019 11:33:16 +0200 +Subject: [PATCH 28/30] workspace-indicator: Show previews in workspace + switcher + +Currently the new horizontal workspace switcher only shows a series of +buttons, with no indication of the workspaces' contents. Go full GNOME 2 +and add tiny draggable preview rectangles that represent the windows +on a particular workspace. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/77 +--- + extensions/workspace-indicator/extension.js | 194 +++++++++++++++++- + extensions/workspace-indicator/stylesheet.css | 22 +- + 2 files changed, 209 insertions(+), 7 deletions(-) + +diff --git a/extensions/workspace-indicator/extension.js b/extensions/workspace-indicator/extension.js +index 48019da..69eef88 100644 +--- a/extensions/workspace-indicator/extension.js ++++ b/extensions/workspace-indicator/extension.js +@@ -2,28 +2,199 @@ + /* exported init enable disable */ + + const { Clutter, Gio, GObject, Meta, St } = imports.gi; ++ ++const DND = imports.ui.dnd; ++const ExtensionUtils = imports.misc.extensionUtils; ++const Main = imports.ui.main; + const PanelMenu = imports.ui.panelMenu; + const PopupMenu = imports.ui.popupMenu; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + +-const Main = imports.ui.main; +- +-const ExtensionUtils = imports.misc.extensionUtils; +- + const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences'; + const WORKSPACE_KEY = 'workspace-names'; + ++let WindowPreview = GObject.registerClass({ ++ GTypeName: 'WorkspaceIndicatorWindowPreview' ++}, class WindowPreview extends St.Button { ++ _init(window) { ++ super._init({ ++ style_class: 'workspace-indicator-window-preview' ++ }); ++ ++ this._delegate = this; ++ DND.makeDraggable(this, { restoreOnSuccess: true }); ++ ++ this._window = window; ++ ++ this.connect('destroy', this._onDestroy.bind(this)); ++ ++ this._sizeChangedId = this._window.connect('size-changed', ++ this._relayout.bind(this)); ++ this._positionChangedId = this._window.connect('position-changed', ++ this._relayout.bind(this)); ++ this._minimizedChangedId = this._window.connect('notify::minimized', ++ this._relayout.bind(this)); ++ this._monitorEnteredId = global.display.connect('window-entered-monitor', ++ this._relayout.bind(this)); ++ this._monitorLeftId = global.display.connect('window-left-monitor', ++ this._relayout.bind(this)); ++ ++ // Do initial layout when we get a parent ++ let id = this.connect('parent-set', () => { ++ this.disconnect(id); ++ if (!this.get_parent()) ++ return; ++ this._laterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { ++ this._laterId = 0; ++ this._relayout(); ++ return false; ++ }); ++ }); ++ ++ this._focusChangedId = global.display.connect('notify::focus-window', ++ this._onFocusChanged.bind(this)); ++ this._onFocusChanged(); ++ } ++ ++ // needed for DND ++ get realWindow() { ++ return this._window.get_compositor_private(); ++ } ++ ++ _onDestroy() { ++ this._window.disconnect(this._sizeChangedId); ++ this._window.disconnect(this._positionChangedId); ++ this._window.disconnect(this._minimizedChangedId); ++ global.display.disconnect(this._monitorEnteredId); ++ global.display.disconnect(this._monitorLeftId); ++ global.display.disconnect(this._focusChangedId); ++ if (this._laterId) ++ Meta.later_remove(this._laterId); ++ } ++ ++ _onFocusChanged() { ++ if (global.display.focus_window == this._window) ++ this.add_style_class_name('active'); ++ else ++ this.remove_style_class_name('active'); ++ } ++ ++ _relayout() { ++ let monitor = Main.layoutManager.findIndexForActor(this); ++ this.visible = monitor == this._window.get_monitor() && ++ this._window.showing_on_its_workspace(); ++ ++ if (!this.visible) ++ return; ++ ++ let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor); ++ let hscale = this.get_parent().allocation.get_width() / workArea.width; ++ let vscale = this.get_parent().allocation.get_height() / workArea.height; ++ ++ let frameRect = this._window.get_frame_rect(); ++ this.set_size( ++ Math.round(Math.min(frameRect.width, workArea.width) * hscale), ++ Math.round(Math.min(frameRect.height, workArea.height) * vscale)); ++ this.set_position( ++ Math.round(frameRect.x * hscale), ++ Math.round(frameRect.y * vscale)); ++ } ++}); ++ + let WorkspaceThumbnail = GObject.registerClass({ + GTypeName: 'WorkspaceIndicatorWorkspaceThumbnail' + }, class WorkspaceThumbnail extends St.Button { + _init(index) { + super._init({ + style_class: 'workspace', ++ child: new Clutter.Actor({ ++ layout_manager: new Clutter.BinLayout(), ++ clip_to_allocation: true ++ }), ++ x_fill: true, ++ y_fill: true + }); + ++ this.connect('destroy', this._onDestroy.bind(this)); ++ + this._index = index; ++ this._delegate = this; // needed for DND ++ ++ this._windowPreviews = new Map(); ++ ++ let workspaceManager = global.workspace_manager; ++ this._workspace = workspaceManager.get_workspace_by_index(index); ++ ++ this._windowAddedId = this._workspace.connect('window-added', ++ (ws, window) => { ++ this._addWindow(window); ++ }); ++ this._windowRemovedId = this._workspace.connect('window-removed', ++ (ws, window) => { ++ this._removeWindow(window); ++ }); ++ this._restackedId = global.display.connect('restacked', ++ this._onRestacked.bind(this)); ++ ++ this._workspace.list_windows().forEach(w => this._addWindow(w)); ++ this._onRestacked(); ++ } ++ ++ acceptDrop(source) { ++ if (!source.realWindow) ++ return false; ++ ++ let window = source.realWindow.get_meta_window(); ++ this._moveWindow(window); ++ return true; ++ } ++ ++ handleDragOver(source) { ++ if (source.realWindow) ++ return DND.DragMotionResult.MOVE_DROP; ++ else ++ return DND.DragMotionResult.CONTINUE; ++ } ++ ++ _addWindow(window) { ++ if (this._windowPreviews.has(window)) ++ return; ++ ++ let preview = new WindowPreview(window); ++ preview.connect('clicked', (a, btn) => this.emit('clicked', btn)); ++ this._windowPreviews.set(window, preview); ++ this.child.add_child(preview); ++ } ++ ++ _removeWindow(window) { ++ let preview = this._windowPreviews.get(window); ++ if (!preview) ++ return; ++ ++ this._windowPreviews.delete(window); ++ preview.destroy(); ++ } ++ ++ _onRestacked() { ++ let lastPreview = null; ++ let windows = global.get_window_actors().map(a => a.meta_window); ++ for (let i = 0; i < windows.length; i++) { ++ let preview = this._windowPreviews.get(windows[i]); ++ if (!preview) ++ continue; ++ ++ this.child.set_child_above_sibling(preview, lastPreview); ++ lastPreview = preview; ++ } ++ } ++ ++ _moveWindow(window) { ++ let monitorIndex = Main.layoutManager.findIndexForActor(this); ++ if (monitorIndex != window.get_monitor()) ++ window.move_to_monitor(monitorIndex); ++ window.change_workspace_by_index(this._index, false); + } + + // eslint-disable-next-line camelcase +@@ -32,8 +203,13 @@ let WorkspaceThumbnail = GObject.registerClass({ + if (ws) + ws.activate(global.get_current_time()); + } +-}); + ++ _onDestroy() { ++ this._workspace.disconnect(this._windowAddedId); ++ this._workspace.disconnect(this._windowRemovedId); ++ global.display.disconnect(this._restackedId); ++ } ++}); + + let WorkspaceIndicator = GObject.registerClass( + class WorkspaceIndicator extends PanelMenu.Button { +@@ -100,6 +276,8 @@ class WorkspaceIndicator extends PanelMenu.Button { + this._settingsChangedId = 0; + } + ++ Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); ++ + super._onDestroy(); + } + +@@ -109,6 +287,12 @@ class WorkspaceIndicator extends PanelMenu.Button { + + this._statusLabel.visible = vertical; + this._thumbnailsBox.visible = !vertical; ++ ++ // Disable offscreen-redirect when showing the workspace switcher ++ // so that clip-to-allocation works ++ Main.panel.set_offscreen_redirect(vertical ++ ? Clutter.OffscreenRedirect.ALWAYS ++ : Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY); + } + + _onWorkspaceSwitched() { +diff --git a/extensions/workspace-indicator/stylesheet.css b/extensions/workspace-indicator/stylesheet.css +index a15081e..8c101e7 100644 +--- a/extensions/workspace-indicator/stylesheet.css ++++ b/extensions/workspace-indicator/stylesheet.css +@@ -1,9 +1,17 @@ +-.panel-workspace-indicator, +-.panel-workspace-indicator-box .workspace { ++.panel-workspace-indicator { + padding: 0 8px; + border: 1px solid #cccccc; + } + ++.panel-workspace-indicator-box { ++ padding: 2px 0; ++} ++ ++.panel-workspace-indicator-box .workspace { ++ border: 1px solid #cccccc; ++ width: 48px; ++} ++ + .panel-workspace-indicator, + .panel-workspace-indicator-box .workspace.active { + background-color: rgba(200, 200, 200, .5); +@@ -17,3 +25,13 @@ + .panel-workspace-indicator-box .workspace:first-child { + border-left-width: 1px; + } ++ ++.workspace-indicator-window-preview { ++ background-color: #252525; ++ border: 1px solid #ccc; ++} ++ ++.workspace-indicator-window-preview { ++ background-color: #353535; ++ border: 2px solid #ccc; ++} +-- +2.21.0 + + +From 06674bf6aff9fb4ae2224a448ba928c1687b5f6b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 2 Jul 2019 17:39:55 +0200 +Subject: [PATCH 29/30] window-list: Move super-key handling into WindowPicker + +We have an option to put a window list on each monitor, so we may have +more than one window picker toggle. We don't want each of those try to +toggle the window picker simultanuously, so move handling of the super +key directly into the picker. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/80 +--- + extensions/window-list/windowPicker.js | 34 ++++++++++++-------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js +index 024fd80..ba0a697 100644 +--- a/extensions/window-list/windowPicker.js ++++ b/extensions/window-list/windowPicker.js +@@ -67,6 +67,8 @@ var WindowPicker = class { + this._visible = false; + this._modal = false; + ++ this._overlayKeyId = 0; ++ + this.actor = new Clutter.Actor(); + + this.actor.connect('destroy', this._onDestroy.bind(this)); +@@ -101,6 +103,15 @@ var WindowPicker = class { + this._updateBackgrounds(); + + Main.uiGroup.insert_child_below(this.actor, global.window_group); ++ ++ if (!Main.sessionMode.hasOverview) { ++ this._overlayKeyId = global.display.connect('overlay-key', () => { ++ if (!this._visible) ++ this.open(); ++ else ++ this.close(); ++ }); ++ } + } + + get visible() { +@@ -188,6 +199,10 @@ var WindowPicker = class { + if (this._monitorsChangedId) + Main.layoutManager.disconnect(this._monitorsChangedId); + this._monitorsChangedId = 0; ++ ++ if (this._overlayKeyId) ++ global.display.disconnect(this._overlayKeyId); ++ this._overlayKeyId = 0; + } + + _updateBackgrounds() { +@@ -227,10 +242,6 @@ class WindowPickerToggle extends St.Button { + toggle_mode: true + }); + +- this._overlayKeyId = 0; +- +- this.connect('destroy', this._onDestroy.bind(this)); +- + this.connect('notify::checked', () => { + if (this.checked) + Main.windowPicker.open(); +@@ -238,23 +249,8 @@ class WindowPickerToggle extends St.Button { + Main.windowPicker.close(); + }); + +- if (!Main.sessionMode.hasOverview) { +- this._overlayKeyId = global.display.connect('overlay-key', () => { +- if (!Main.windowPicker.visible) +- Main.windowPicker.open(); +- else +- Main.windowPicker.close(); +- }); +- } +- + Main.windowPicker.connect('open-state-changed', () => { + this.checked = Main.windowPicker.visible; + }); + } +- +- _onDestroy() { +- if (this._overlayKeyId) +- global.display.disconnect(this._overlayKeyId); +- this._overlayKeyId == 0; +- } + }); +-- +2.21.0 + + +From c37d082487cce3548844c150d1976bf1735552c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 2 Jul 2019 18:12:31 +0200 +Subject: [PATCH 30/30] window-list: Handle closing window picker with Escape + +Just like the overview can be closed with Escape, it makes sense to +allow the same for the window picker (in addition to pressing super +repeatedly). + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/80 +--- + extensions/window-list/windowPicker.js | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/extensions/window-list/windowPicker.js b/extensions/window-list/windowPicker.js +index ba0a697..12a7627 100644 +--- a/extensions/window-list/windowPicker.js ++++ b/extensions/window-list/windowPicker.js +@@ -68,6 +68,7 @@ var WindowPicker = class { + this._modal = false; + + this._overlayKeyId = 0; ++ this._stageKeyPressId = 0; + + this.actor = new Clutter.Actor(); + +@@ -132,6 +133,16 @@ var WindowPicker = class { + this._fakeOverviewAnimation(); + this._workspacesDisplay.show(false); + ++ this._stageKeyPressId = global.stage.connect('key-press-event', ++ (a, event) => { ++ let sym = event.get_key_symbol(); ++ if (sym == Clutter.KEY_Escape) { ++ this.close(); ++ return Clutter.EVENT_STOP; ++ } ++ return Clutter.EVENT_PROPAGATE; ++ }); ++ + this.emit('open-state-changed', this._visible); + } + +@@ -151,6 +162,9 @@ var WindowPicker = class { + this._fakeOverviewVisible(false); + }); + ++ global.stage.disconnect(this._stageKeyPressId); ++ this._stageKeyPressId = 0; ++ + this.emit('open-state-changed', this._visible); + } + +@@ -203,6 +217,10 @@ var WindowPicker = class { + if (this._overlayKeyId) + global.display.disconnect(this._overlayKeyId); + this._overlayKeyId = 0; ++ ++ if (this._stageKeyPressId) ++ global.stage.disconnect(this._stageKeyPressId); ++ this._stageKeyPressId = 0; + } + + _updateBackgrounds() { +-- +2.21.0 + diff --git a/SOURCES/resurrect-system-monitor.patch b/SOURCES/resurrect-system-monitor.patch new file mode 100644 index 0000000..9c4daf4 --- /dev/null +++ b/SOURCES/resurrect-system-monitor.patch @@ -0,0 +1,1311 @@ +From 7c3b0af4fde0b542089f2b0c84250404eef0ecca Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 17 May 2017 19:13:50 +0200 +Subject: [PATCH 1/5] extensions: Resurrect systemMonitor extension + +The extension was removed upstream because: + - it hooks into the message tray that was removed + - it was known to have performance issues + - there are plenty of alternatives + +Those aren't good enough reasons for dropping it downstream +as well though, so we need to bring it back ... + +This reverts commit c9a6421f362cd156cf731289eadc11f44f6970ac. +--- + extensions/systemMonitor/extension.js | 376 ++++++++++++++++++++++ + extensions/systemMonitor/meson.build | 5 + + extensions/systemMonitor/metadata.json.in | 11 + + extensions/systemMonitor/stylesheet.css | 35 ++ + meson.build | 1 + + 5 files changed, 428 insertions(+) + create mode 100644 extensions/systemMonitor/extension.js + create mode 100644 extensions/systemMonitor/meson.build + create mode 100644 extensions/systemMonitor/metadata.json.in + create mode 100644 extensions/systemMonitor/stylesheet.css + +diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js +new file mode 100644 +index 0000000..7b09df0 +--- /dev/null ++++ b/extensions/systemMonitor/extension.js +@@ -0,0 +1,376 @@ ++/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ ++ ++const Clutter = imports.gi.Clutter; ++const GTop = imports.gi.GTop; ++const Lang = imports.lang; ++const Mainloop = imports.mainloop; ++const St = imports.gi.St; ++const Shell = imports.gi.Shell; ++ ++const Main = imports.ui.main; ++const Tweener = imports.ui.tweener; ++ ++const Gettext = imports.gettext.domain('gnome-shell-extensions'); ++const _ = Gettext.gettext; ++ ++const ExtensionUtils = imports.misc.extensionUtils; ++const Me = ExtensionUtils.getCurrentExtension(); ++const Convenience = Me.imports.convenience; ++ ++const INDICATOR_UPDATE_INTERVAL = 500; ++const INDICATOR_NUM_GRID_LINES = 3; ++ ++const ITEM_LABEL_SHOW_TIME = 0.15; ++const ITEM_LABEL_HIDE_TIME = 0.1; ++const ITEM_HOVER_TIMEOUT = 300; ++ ++const Indicator = new Lang.Class({ ++ Name: 'SystemMonitor.Indicator', ++ ++ _init: function() { ++ this._initValues(); ++ this.drawing_area = new St.DrawingArea({ reactive: true }); ++ this.drawing_area.connect('repaint', Lang.bind(this, this._draw)); ++ this.drawing_area.connect('button-press-event', function() { ++ let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop'); ++ app.open_new_window(-1); ++ return true; ++ }); ++ ++ this.actor = new St.Bin({ style_class: "extension-systemMonitor-indicator-area", ++ reactive: true, track_hover: true, ++ x_fill: true, y_fill: true }); ++ this.actor.add_actor(this.drawing_area); ++ ++ this._timeout = Mainloop.timeout_add(INDICATOR_UPDATE_INTERVAL, Lang.bind(this, function () { ++ this._updateValues(); ++ this.drawing_area.queue_repaint(); ++ return true; ++ })); ++ }, ++ ++ showLabel: function() { ++ if (this.label == null) ++ return; ++ ++ this.label.opacity = 0; ++ this.label.show(); ++ ++ let [stageX, stageY] = this.actor.get_transformed_position(); ++ ++ let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1; ++ let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1; ++ ++ let labelWidth = this.label.width; ++ let labelHeight = this.label.height; ++ let xOffset = Math.floor((itemWidth - labelWidth) / 2) ++ ++ let x = stageX + xOffset; ++ ++ let node = this.label.get_theme_node(); ++ let yOffset = node.get_length('-y-offset'); ++ ++ let y = stageY - this.label.get_height() - yOffset; ++ ++ this.label.set_position(x, y); ++ Tweener.addTween(this.label, ++ { opacity: 255, ++ time: ITEM_LABEL_SHOW_TIME, ++ transition: 'easeOutQuad', ++ }); ++ }, ++ ++ setLabelText: function(text) { ++ if (this.label == null) ++ this.label = new St.Label({ style_class: 'extension-systemMonitor-indicator-label'}); ++ ++ this.label.set_text(text); ++ Main.layoutManager.addChrome(this.label); ++ this.label.hide(); ++ }, ++ ++ hideLabel: function () { ++ Tweener.addTween(this.label, ++ { opacity: 0, ++ time: ITEM_LABEL_HIDE_TIME, ++ transition: 'easeOutQuad', ++ onComplete: Lang.bind(this, function() { ++ this.label.hide(); ++ }) ++ }); ++ }, ++ ++ destroy: function() { ++ Mainloop.source_remove(this._timeout); ++ ++ this.actor.destroy(); ++ if (this.label) ++ this.label.destroy(); ++ }, ++ ++ _initValues: function() { ++ }, ++ ++ _updateValues: function() { ++ }, ++ ++ _draw: function(area) { ++ let [width, height] = area.get_surface_size(); ++ let themeNode = this.actor.get_theme_node(); ++ let cr = area.get_context(); ++ ++ //draw the background grid ++ let color = themeNode.get_color(this.gridColor); ++ let gridOffset = Math.floor(height / (INDICATOR_NUM_GRID_LINES + 1)); ++ for (let i = 1; i <= INDICATOR_NUM_GRID_LINES; ++i) { ++ cr.moveTo(0, i * gridOffset + .5); ++ cr.lineTo(width, i * gridOffset + .5); ++ } ++ Clutter.cairo_set_source_color(cr, color); ++ cr.setLineWidth(1); ++ cr.setDash([4,1], 0); ++ cr.stroke(); ++ ++ //draw the foreground ++ ++ function makePath(values, reverse, nudge) { ++ if (nudge == null) { ++ nudge = 0; ++ } ++ //if we are going in reverse, we are completing the bottom of a chart, so use lineTo ++ if (reverse) { ++ cr.lineTo(values.length - 1, (1 - values[values.length - 1]) * height + nudge); ++ for (let k = values.length - 2; k >= 0; --k) { ++ cr.lineTo(k, (1 - values[k]) * height + nudge); ++ } ++ } else { ++ cr.moveTo(0, (1 - values[0]) * height + nudge); ++ for (let k = 1; k < values.length; ++k) { ++ cr.lineTo(k, (1 - values[k]) * height + nudge); ++ } ++ ++ } ++ } ++ ++ let renderStats = this.renderStats; ++ ++ // Make sure we don't have more sample points than pixels ++ renderStats.map(Lang.bind(this, function(k){ ++ let stat = this.stats[k]; ++ if (stat.values.length > width) { ++ stat.values = stat.values.slice(stat.values.length - width, stat.values.length); ++ } ++ })); ++ ++ for (let i = 0; i < renderStats.length; ++i) { ++ let stat = this.stats[renderStats[i]]; ++ // We outline at full opacity and fill with 40% opacity ++ let outlineColor = themeNode.get_color(stat.color); ++ let color = new Clutter.Color(outlineColor); ++ color.alpha = color.alpha * .4; ++ ++ // Render the background between us and the next level ++ makePath(stat.values, false); ++ // If there is a process below us, render the cpu between us and it, otherwise, ++ // render to the bottom of the chart ++ if (i == renderStats.length - 1) { ++ cr.lineTo(stat.values.length - 1, height); ++ cr.lineTo(0, height); ++ cr.closePath(); ++ } else { ++ let nextStat = this.stats[renderStats[i+1]]; ++ makePath(nextStat.values, true); ++ } ++ cr.closePath() ++ Clutter.cairo_set_source_color(cr, color); ++ cr.fill(); ++ ++ // Render the outline of this level ++ makePath(stat.values, false, .5); ++ Clutter.cairo_set_source_color(cr, outlineColor); ++ cr.setLineWidth(1.0); ++ cr.setDash([], 0); ++ cr.stroke(); ++ } ++ } ++}); ++ ++const CpuIndicator = new Lang.Class({ ++ Name: 'SystemMonitor.CpuIndicator', ++ Extends: Indicator, ++ ++ _init: function() { ++ this.parent(); ++ ++ this.gridColor = '-grid-color'; ++ this.renderStats = [ 'cpu-user', 'cpu-sys', 'cpu-iowait' ]; ++ ++ // Make sure renderStats is sorted as necessary for rendering ++ let renderStatOrder = {'cpu-total': 0, 'cpu-user': 1, 'cpu-sys': 2, 'cpu-iowait': 3}; ++ this.renderStats = this.renderStats.sort(function(a,b) { ++ return renderStatOrder[a] - renderStatOrder[b]; ++ }); ++ ++ this.setLabelText(_("CPU")); ++ }, ++ ++ _initValues: function() { ++ this._prev = new GTop.glibtop_cpu; ++ GTop.glibtop_get_cpu(this._prev); ++ ++ this.stats = { ++ 'cpu-user': {color: '-cpu-user-color', values: []}, ++ 'cpu-sys': {color: '-cpu-sys-color', values: []}, ++ 'cpu-iowait': {color: '-cpu-iowait-color', values: []}, ++ 'cpu-total': {color: '-cpu-total-color', values: []} ++ }; ++ }, ++ ++ _updateValues: function() { ++ let cpu = new GTop.glibtop_cpu; ++ let t = 0.0; ++ GTop.glibtop_get_cpu(cpu); ++ let total = cpu.total - this._prev.total; ++ let user = cpu.user - this._prev.user; ++ let sys = cpu.sys - this._prev.sys; ++ let iowait = cpu.iowait - this._prev.iowait; ++ let idle = cpu.idle - this._prev.idle; ++ ++ t += iowait / total; ++ this.stats['cpu-iowait'].values.push(t); ++ t += sys / total; ++ this.stats['cpu-sys'].values.push(t); ++ t += user / total; ++ this.stats['cpu-user'].values.push(t); ++ this.stats['cpu-total'].values.push(1 - idle / total); ++ ++ this._prev = cpu; ++ } ++}); ++ ++const MemoryIndicator = new Lang.Class({ ++ Name: 'SystemMonitor.MemoryIndicator', ++ Extends: Indicator, ++ ++ _init: function() { ++ this.parent(); ++ ++ this.gridColor = '-grid-color'; ++ this.renderStats = [ 'mem-user', 'mem-other', 'mem-cached' ]; ++ ++ // Make sure renderStats is sorted as necessary for rendering ++ let renderStatOrder = { 'mem-cached': 0, 'mem-other': 1, 'mem-user': 2 }; ++ this.renderStats = this.renderStats.sort(function(a,b) { ++ return renderStatOrder[a] - renderStatOrder[b]; ++ }); ++ ++ this.setLabelText(_("Memory")); ++ }, ++ ++ _initValues: function() { ++ this.mem = new GTop.glibtop_mem; ++ this.stats = { ++ 'mem-user': { color: "-mem-user-color", values: [] }, ++ 'mem-other': { color: "-mem-other-color", values: [] }, ++ 'mem-cached': { color: "-mem-cached-color", values: [] } ++ }; ++ }, ++ ++ _updateValues: function() { ++ GTop.glibtop_get_mem(this.mem); ++ ++ let t = this.mem.user / this.mem.total; ++ this.stats['mem-user'].values.push(t); ++ t += (this.mem.used - this.mem.user - this.mem.cached) / this.mem.total; ++ this.stats['mem-other'].values.push(t); ++ t += this.mem.cached / this.mem.total; ++ this.stats['mem-cached'].values.push(t); ++ } ++}); ++ ++const INDICATORS = [CpuIndicator, MemoryIndicator]; ++ ++const Extension = new Lang.Class({ ++ Name: 'SystemMonitor.Extension', ++ ++ _init: function() { ++ Convenience.initTranslations(); ++ ++ this._showLabelTimeoutId = 0; ++ this._resetHoverTimeoutId = 0; ++ this._labelShowing = false; ++ }, ++ ++ enable: function() { ++ this._box = new St.BoxLayout({ style_class: 'extension-systemMonitor-container', ++ x_align: Clutter.ActorAlign.START, ++ x_expand: true }); ++ this._indicators = [ ]; ++ ++ for (let i = 0; i < INDICATORS.length; i++) { ++ let indicator = new (INDICATORS[i])(); ++ ++ indicator.actor.connect('notify::hover', Lang.bind(this, function() { ++ this._onHover(indicator); ++ })); ++ this._box.add_actor(indicator.actor); ++ this._indicators.push(indicator); ++ } ++ ++ this._boxHolder = new St.BoxLayout({ x_expand: true, ++ y_expand: true, ++ x_align: Clutter.ActorAlign.START, ++ }); ++ let menuButton = Main.messageTray._messageTrayMenuButton.actor; ++ Main.messageTray.actor.remove_child(menuButton); ++ Main.messageTray.actor.add_child(this._boxHolder); ++ ++ this._boxHolder.add_child(this._box); ++ this._boxHolder.add_child(menuButton); ++ }, ++ ++ disable: function() { ++ this._indicators.forEach(function(i) { i.destroy(); }); ++ ++ let menuButton = Main.messageTray._messageTrayMenuButton.actor; ++ this._boxHolder.remove_child(menuButton); ++ Main.messageTray.actor.add_child(menuButton); ++ ++ this._box.destroy(); ++ this._boxHolder.destroy(); ++ }, ++ ++ _onHover: function (item) { ++ if (item.actor.get_hover()) { ++ if (this._showLabelTimeoutId == 0) { ++ let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT; ++ this._showLabelTimeoutId = Mainloop.timeout_add(timeout, ++ Lang.bind(this, function() { ++ this._labelShowing = true; ++ item.showLabel(); ++ return false; ++ })); ++ if (this._resetHoverTimeoutId > 0) { ++ Mainloop.source_remove(this._resetHoverTimeoutId); ++ this._resetHoverTimeoutId = 0; ++ } ++ } ++ } else { ++ if (this._showLabelTimeoutId > 0) ++ Mainloop.source_remove(this._showLabelTimeoutId); ++ this._showLabelTimeoutId = 0; ++ item.hideLabel(); ++ if (this._labelShowing) { ++ this._resetHoverTimeoutId = Mainloop.timeout_add(ITEM_HOVER_TIMEOUT, ++ Lang.bind(this, function() { ++ this._labelShowing = false; ++ return false; ++ })); ++ } ++ } ++ }, ++}); ++ ++function init() { ++ return new Extension(); ++} +diff --git a/extensions/systemMonitor/meson.build b/extensions/systemMonitor/meson.build +new file mode 100644 +index 0000000..48504f6 +--- /dev/null ++++ b/extensions/systemMonitor/meson.build +@@ -0,0 +1,5 @@ ++extension_data += configure_file( ++ input: metadata_name + '.in', ++ output: metadata_name, ++ configuration: metadata_conf ++) +diff --git a/extensions/systemMonitor/metadata.json.in b/extensions/systemMonitor/metadata.json.in +new file mode 100644 +index 0000000..fa75007 +--- /dev/null ++++ b/extensions/systemMonitor/metadata.json.in +@@ -0,0 +1,11 @@ ++{ ++ "shell-version": ["@shell_current@" ], ++ "uuid": "@uuid@", ++ "extension-id": "@extension_id@", ++ "settings-schema": "@gschemaname@", ++ "gettext-domain": "@gettext_domain@", ++ "original-author": "zaspire@rambler.ru", ++ "name": "SystemMonitor", ++ "description": "System monitor showing CPU and memory usage in the message tray.", ++ "url": "@url@" ++} +diff --git a/extensions/systemMonitor/stylesheet.css b/extensions/systemMonitor/stylesheet.css +new file mode 100644 +index 0000000..13f95ec +--- /dev/null ++++ b/extensions/systemMonitor/stylesheet.css +@@ -0,0 +1,35 @@ ++.extension-systemMonitor-container { ++ spacing: 5px; ++ padding-left: 5px; ++ padding-right: 5px; ++ padding-bottom: 10px; ++ padding-top: 10px; ++} ++ ++.extension-systemMonitor-indicator-area { ++ border: 1px solid #8d8d8d; ++ border-radius: 3px; ++ width: 100px; ++ /* message tray is 72px, so 20px padding of the container, ++ 2px of border, makes it 50px */ ++ height: 50px; ++ -grid-color: #575757; ++ -cpu-total-color: rgb(0,154,62); ++ -cpu-user-color: rgb(69,154,0); ++ -cpu-sys-color: rgb(255,253,81); ++ -cpu-iowait-color: rgb(210,148,0); ++ -mem-user-color: rgb(210,148,0); ++ -mem-cached-color: rgb(90,90,90); ++ -mem-other-color: rgb(205,203,41); ++ background-color: #1e1e1e; ++} ++ ++.extension-systemMonitor-indicator-label { ++ border-radius: 7px; ++ padding: 4px 12px; ++ background-color: rgba(0,0,0,0.9); ++ text-align: center; ++ -y-offset: 8px; ++ font-size: 9pt; ++ font-weight: bold; ++} +diff --git a/meson.build b/meson.build +index 6e8c41f..6764f9a 100644 +--- a/meson.build ++++ b/meson.build +@@ -55,6 +55,7 @@ all_extensions += [ + 'native-window-placement', + 'no-hot-corner', + 'panel-favorites', ++ 'systemMonitor', + 'top-icons', + 'updates-dialog', + 'user-theme', +-- +2.21.0 + + +From ddf4d70df56321366a2cb8b89689d59be4dbb718 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 17 May 2019 22:55:48 +0000 +Subject: [PATCH 2/5] systemMonitor: Modernise code + + - port to ES6 classes + - replace Lang.bind() + - destructure imports + - fix style issues (stray/missing spaces/semi-colons, indent, ...) +--- + extensions/systemMonitor/extension.js | 377 +++++++++++++------------- + 1 file changed, 192 insertions(+), 185 deletions(-) + +diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js +index 7b09df0..89f8916 100644 +--- a/extensions/systemMonitor/extension.js ++++ b/extensions/systemMonitor/extension.js +@@ -1,22 +1,16 @@ + /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ + +-const Clutter = imports.gi.Clutter; +-const GTop = imports.gi.GTop; +-const Lang = imports.lang; +-const Mainloop = imports.mainloop; +-const St = imports.gi.St; +-const Shell = imports.gi.Shell; ++/* exported init */ + ++const { Clutter, GLib, GTop, Shell, St } = imports.gi; ++ ++const ExtensionUtils = imports.misc.extensionUtils; + const Main = imports.ui.main; + const Tweener = imports.ui.tweener; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); + const _ = Gettext.gettext; + +-const ExtensionUtils = imports.misc.extensionUtils; +-const Me = ExtensionUtils.getCurrentExtension(); +-const Convenience = Me.imports.convenience; +- + const INDICATOR_UPDATE_INTERVAL = 500; + const INDICATOR_NUM_GRID_LINES = 3; + +@@ -24,32 +18,38 @@ const ITEM_LABEL_SHOW_TIME = 0.15; + const ITEM_LABEL_HIDE_TIME = 0.1; + const ITEM_HOVER_TIMEOUT = 300; + +-const Indicator = new Lang.Class({ +- Name: 'SystemMonitor.Indicator', +- +- _init: function() { ++const Indicator = class { ++ constructor() { + this._initValues(); +- this.drawing_area = new St.DrawingArea({ reactive: true }); +- this.drawing_area.connect('repaint', Lang.bind(this, this._draw)); +- this.drawing_area.connect('button-press-event', function() { ++ this._drawingArea = new St.DrawingArea({ reactive: true }); ++ this._drawingArea.connect('repaint', this._draw.bind(this)); ++ this._drawingArea.connect('button-press-event', () => { + let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop'); + app.open_new_window(-1); + return true; + }); + +- this.actor = new St.Bin({ style_class: "extension-systemMonitor-indicator-area", +- reactive: true, track_hover: true, +- x_fill: true, y_fill: true }); +- this.actor.add_actor(this.drawing_area); ++ this.actor = new St.Bin({ ++ style_class: 'extension-systemMonitor-indicator-area', ++ reactive: true, ++ track_hover: true, ++ x_fill: true, ++ y_fill: true ++ }); ++ this.actor.add_actor(this._drawingArea); + +- this._timeout = Mainloop.timeout_add(INDICATOR_UPDATE_INTERVAL, Lang.bind(this, function () { +- this._updateValues(); +- this.drawing_area.queue_repaint(); +- return true; +- })); +- }, ++ this.actor.connect('destroy', this._onDestroy.bind(this)); + +- showLabel: function() { ++ this._timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ++ INDICATOR_UPDATE_INTERVAL, ++ () => { ++ this._updateValues(); ++ this._drawingArea.queue_repaint(); ++ return GLib.SOURCE_CONTINUE; ++ }); ++ } ++ ++ showLabel() { + if (this.label == null) + return; + +@@ -58,12 +58,10 @@ const Indicator = new Lang.Class({ + + let [stageX, stageY] = this.actor.get_transformed_position(); + +- let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1; +- let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1; ++ let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1; + +- let labelWidth = this.label.width; +- let labelHeight = this.label.height; +- let xOffset = Math.floor((itemWidth - labelWidth) / 2) ++ let labelWidth = this.label.width; ++ let xOffset = Math.floor((itemWidth - labelWidth) / 2); + + let x = stageX + xOffset; + +@@ -73,48 +71,51 @@ const Indicator = new Lang.Class({ + let y = stageY - this.label.get_height() - yOffset; + + this.label.set_position(x, y); +- Tweener.addTween(this.label, +- { opacity: 255, +- time: ITEM_LABEL_SHOW_TIME, +- transition: 'easeOutQuad', +- }); +- }, +- +- setLabelText: function(text) { ++ Tweener.addTween(this.label, { ++ opacity: 255, ++ time: ITEM_LABEL_SHOW_TIME, ++ transition: 'easeOutQuad', ++ }); ++ } ++ ++ setLabelText(text) { + if (this.label == null) +- this.label = new St.Label({ style_class: 'extension-systemMonitor-indicator-label'}); ++ this.label = new St.Label({ ++ style_class: 'extension-systemMonitor-indicator-label' ++ }); + + this.label.set_text(text); + Main.layoutManager.addChrome(this.label); + this.label.hide(); +- }, +- +- hideLabel: function () { +- Tweener.addTween(this.label, +- { opacity: 0, +- time: ITEM_LABEL_HIDE_TIME, +- transition: 'easeOutQuad', +- onComplete: Lang.bind(this, function() { +- this.label.hide(); +- }) +- }); +- }, +- +- destroy: function() { +- Mainloop.source_remove(this._timeout); ++ } + ++ hideLabel() { ++ Tweener.addTween(this.label, { ++ opacity: 0, ++ time: ITEM_LABEL_HIDE_TIME, ++ transition: 'easeOutQuad', ++ onComplete: () => this.label.hide() ++ }); ++ } ++ ++ destroy() { + this.actor.destroy(); +- if (this.label) +- this.label.destroy(); +- }, ++ } ++ ++ _onDestroy() { ++ GLib.source_remove(this._timeout); ++ ++ if (this.label) ++ this.label.destroy(); ++ } + +- _initValues: function() { +- }, ++ _initValues() { ++ } + +- _updateValues: function() { +- }, ++ _updateValues() { ++ } + +- _draw: function(area) { ++ _draw(area) { + let [width, height] = area.get_surface_size(); + let themeNode = this.actor.get_theme_node(); + let cr = area.get_context(); +@@ -123,12 +124,12 @@ const Indicator = new Lang.Class({ + let color = themeNode.get_color(this.gridColor); + let gridOffset = Math.floor(height / (INDICATOR_NUM_GRID_LINES + 1)); + for (let i = 1; i <= INDICATOR_NUM_GRID_LINES; ++i) { +- cr.moveTo(0, i * gridOffset + .5); +- cr.lineTo(width, i * gridOffset + .5); ++ cr.moveTo(0, i * gridOffset + .5); ++ cr.lineTo(width, i * gridOffset + .5); + } + Clutter.cairo_set_source_color(cr, color); + cr.setLineWidth(1); +- cr.setDash([4,1], 0); ++ cr.setDash([4, 1], 0); + cr.stroke(); + + //draw the foreground +@@ -155,12 +156,12 @@ const Indicator = new Lang.Class({ + let renderStats = this.renderStats; + + // Make sure we don't have more sample points than pixels +- renderStats.map(Lang.bind(this, function(k){ ++ renderStats.map(k => { + let stat = this.stats[k]; + if (stat.values.length > width) { + stat.values = stat.values.slice(stat.values.length - width, stat.values.length); + } +- })); ++ }); + + for (let i = 0; i < renderStats.length; ++i) { + let stat = this.stats[renderStats[i]]; +@@ -178,10 +179,10 @@ const Indicator = new Lang.Class({ + cr.lineTo(0, height); + cr.closePath(); + } else { +- let nextStat = this.stats[renderStats[i+1]]; ++ let nextStat = this.stats[renderStats[i + 1]]; + makePath(nextStat.values, true); + } +- cr.closePath() ++ cr.closePath(); + Clutter.cairo_set_source_color(cr, color); + cr.fill(); + +@@ -193,40 +194,42 @@ const Indicator = new Lang.Class({ + cr.stroke(); + } + } +-}); +- +-const CpuIndicator = new Lang.Class({ +- Name: 'SystemMonitor.CpuIndicator', +- Extends: Indicator, ++}; + +- _init: function() { +- this.parent(); ++const CpuIndicator = class extends Indicator { ++ constructor() { ++ super(); + + this.gridColor = '-grid-color'; +- this.renderStats = [ 'cpu-user', 'cpu-sys', 'cpu-iowait' ]; ++ this.renderStats = ['cpu-user', 'cpu-sys', 'cpu-iowait']; + + // Make sure renderStats is sorted as necessary for rendering +- let renderStatOrder = {'cpu-total': 0, 'cpu-user': 1, 'cpu-sys': 2, 'cpu-iowait': 3}; +- this.renderStats = this.renderStats.sort(function(a,b) { ++ let renderStatOrder = { ++ 'cpu-total': 0, ++ 'cpu-user': 1, ++ 'cpu-sys': 2, ++ 'cpu-iowait': 3 ++ }; ++ this.renderStats = this.renderStats.sort((a, b) => { + return renderStatOrder[a] - renderStatOrder[b]; + }); + +- this.setLabelText(_("CPU")); +- }, ++ this.setLabelText(_('CPU')); ++ } + +- _initValues: function() { ++ _initValues() { + this._prev = new GTop.glibtop_cpu; + GTop.glibtop_get_cpu(this._prev); + + this.stats = { +- 'cpu-user': {color: '-cpu-user-color', values: []}, +- 'cpu-sys': {color: '-cpu-sys-color', values: []}, +- 'cpu-iowait': {color: '-cpu-iowait-color', values: []}, +- 'cpu-total': {color: '-cpu-total-color', values: []} +- }; +- }, +- +- _updateValues: function() { ++ 'cpu-user': { color: '-cpu-user-color', values: [] }, ++ 'cpu-sys': { color: '-cpu-sys-color', values: [] }, ++ 'cpu-iowait': { color: '-cpu-iowait-color', values: [] }, ++ 'cpu-total': { color: '-cpu-total-color', values: [] } ++ }; ++ } ++ ++ _updateValues() { + let cpu = new GTop.glibtop_cpu; + let t = 0.0; + GTop.glibtop_get_cpu(cpu); +@@ -246,37 +249,34 @@ const CpuIndicator = new Lang.Class({ + + this._prev = cpu; + } +-}); ++}; + +-const MemoryIndicator = new Lang.Class({ +- Name: 'SystemMonitor.MemoryIndicator', +- Extends: Indicator, +- +- _init: function() { +- this.parent(); ++const MemoryIndicator = class extends Indicator { ++ constructor() { ++ super(); + + this.gridColor = '-grid-color'; +- this.renderStats = [ 'mem-user', 'mem-other', 'mem-cached' ]; ++ this.renderStats = ['mem-user', 'mem-other', 'mem-cached']; + + // Make sure renderStats is sorted as necessary for rendering + let renderStatOrder = { 'mem-cached': 0, 'mem-other': 1, 'mem-user': 2 }; +- this.renderStats = this.renderStats.sort(function(a,b) { ++ this.renderStats = this.renderStats.sort((a, b) => { + return renderStatOrder[a] - renderStatOrder[b]; + }); + +- this.setLabelText(_("Memory")); +- }, ++ this.setLabelText(_('Memory')); ++ } + +- _initValues: function() { ++ _initValues() { + this.mem = new GTop.glibtop_mem; + this.stats = { +- 'mem-user': { color: "-mem-user-color", values: [] }, +- 'mem-other': { color: "-mem-other-color", values: [] }, +- 'mem-cached': { color: "-mem-cached-color", values: [] } +- }; +- }, ++ 'mem-user': { color: '-mem-user-color', values: [] }, ++ 'mem-other': { color: '-mem-other-color', values: [] }, ++ 'mem-cached': { color: '-mem-cached-color', values: [] } ++ }; ++ } + +- _updateValues: function() { ++ _updateValues() { + GTop.glibtop_get_mem(this.mem); + + let t = this.mem.user / this.mem.total; +@@ -286,90 +286,97 @@ const MemoryIndicator = new Lang.Class({ + t += this.mem.cached / this.mem.total; + this.stats['mem-cached'].values.push(t); + } +-}); ++}; + + const INDICATORS = [CpuIndicator, MemoryIndicator]; + +-const Extension = new Lang.Class({ +- Name: 'SystemMonitor.Extension', +- +- _init: function() { +- Convenience.initTranslations(); +- +- this._showLabelTimeoutId = 0; +- this._resetHoverTimeoutId = 0; +- this._labelShowing = false; +- }, +- +- enable: function() { +- this._box = new St.BoxLayout({ style_class: 'extension-systemMonitor-container', +- x_align: Clutter.ActorAlign.START, +- x_expand: true }); +- this._indicators = [ ]; +- +- for (let i = 0; i < INDICATORS.length; i++) { +- let indicator = new (INDICATORS[i])(); +- +- indicator.actor.connect('notify::hover', Lang.bind(this, function() { +- this._onHover(indicator); +- })); +- this._box.add_actor(indicator.actor); +- this._indicators.push(indicator); +- } +- +- this._boxHolder = new St.BoxLayout({ x_expand: true, +- y_expand: true, +- x_align: Clutter.ActorAlign.START, +- }); +- let menuButton = Main.messageTray._messageTrayMenuButton.actor; +- Main.messageTray.actor.remove_child(menuButton); +- Main.messageTray.actor.add_child(this._boxHolder); +- +- this._boxHolder.add_child(this._box); +- this._boxHolder.add_child(menuButton); +- }, +- +- disable: function() { +- this._indicators.forEach(function(i) { i.destroy(); }); +- +- let menuButton = Main.messageTray._messageTrayMenuButton.actor; +- this._boxHolder.remove_child(menuButton); +- Main.messageTray.actor.add_child(menuButton); +- +- this._box.destroy(); +- this._boxHolder.destroy(); +- }, +- +- _onHover: function (item) { ++class Extension { ++ constructor() { ++ ExtensionUtils.initTranslations(); ++ ++ this._showLabelTimeoutId = 0; ++ this._resetHoverTimeoutId = 0; ++ this._labelShowing = false; ++ } ++ ++ enable() { ++ this._box = new St.BoxLayout({ ++ style_class: 'extension-systemMonitor-container', ++ x_align: Clutter.ActorAlign.START, ++ x_expand: true ++ }); ++ this._indicators = []; ++ ++ for (let i = 0; i < INDICATORS.length; i++) { ++ let indicator = new (INDICATORS[i])(); ++ ++ indicator.actor.connect('notify::hover', () => { ++ this._onHover(indicator); ++ }); ++ this._box.add_actor(indicator.actor); ++ this._indicators.push(indicator); ++ } ++ ++ this._boxHolder = new St.BoxLayout({ ++ x_expand: true, ++ y_expand: true, ++ x_align: Clutter.ActorAlign.START, ++ }); ++ let menuButton = Main.messageTray._messageTrayMenuButton.actor; ++ Main.messageTray.actor.remove_child(menuButton); ++ Main.messageTray.actor.add_child(this._boxHolder); ++ ++ this._boxHolder.add_child(this._box); ++ this._boxHolder.add_child(menuButton); ++ } ++ ++ disable() { ++ this._indicators.forEach(i => i.destroy()); ++ ++ let menuButton = Main.messageTray._messageTrayMenuButton.actor; ++ this._boxHolder.remove_child(menuButton); ++ Main.messageTray.actor.add_child(menuButton); ++ ++ this._box.destroy(); ++ this._boxHolder.destroy(); ++ } ++ ++ _onHover(item) { + if (item.actor.get_hover()) { +- if (this._showLabelTimeoutId == 0) { +- let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT; +- this._showLabelTimeoutId = Mainloop.timeout_add(timeout, +- Lang.bind(this, function() { +- this._labelShowing = true; +- item.showLabel(); +- return false; +- })); +- if (this._resetHoverTimeoutId > 0) { +- Mainloop.source_remove(this._resetHoverTimeoutId); +- this._resetHoverTimeoutId = 0; +- } ++ if (this._showLabelTimeoutId) ++ return; ++ ++ let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT; ++ this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ++ timeout, ++ () => { ++ this._labelShowing = true; ++ item.showLabel(); ++ this._showLabelTimeoutId = 0; ++ return GLib.SOURCE_REMOVE; ++ }); ++ ++ if (this._resetHoverTimeoutId > 0) { ++ GLib.source_remove(this._resetHoverTimeoutId); ++ this._resetHoverTimeoutId = 0; + } + } else { + if (this._showLabelTimeoutId > 0) +- Mainloop.source_remove(this._showLabelTimeoutId); ++ GLib.source_remove(this._showLabelTimeoutId); + this._showLabelTimeoutId = 0; + item.hideLabel(); +- if (this._labelShowing) { +- this._resetHoverTimeoutId = Mainloop.timeout_add(ITEM_HOVER_TIMEOUT, +- Lang.bind(this, function() { +- this._labelShowing = false; +- return false; +- })); +- } ++ if (!this._labelShowing) ++ return; ++ ++ this._resetHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ++ ITEM_HOVER_TIMEOUT, ++ () => { ++ this._labelShowing = false; ++ return GLib.SOURCE_REMOVE; ++ }); + } +- }, +-}); ++ } ++} + + function init() { + return new Extension(); +-- +2.21.0 + + +From e7ea49cd416e8ede9767f5ade46a06764d1e9a5b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 17 May 2017 19:31:58 +0200 +Subject: [PATCH 3/5] systemMonitor: Move indicators to calendar + +The message tray joined the invisible choir, so we have to find +a new home for the extension UI. The message list in the calendar +drop-down looks like the best option, given that it replaced the +old tray (and also took over the old keyboard shortcut to bring +it up quickly). +--- + extensions/systemMonitor/extension.js | 65 ++++++++++++------------- + extensions/systemMonitor/stylesheet.css | 14 ------ + 2 files changed, 31 insertions(+), 48 deletions(-) + +diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js +index 89f8916..0188960 100644 +--- a/extensions/systemMonitor/extension.js ++++ b/extensions/systemMonitor/extension.js +@@ -3,9 +3,11 @@ + /* exported init */ + + const { Clutter, GLib, GTop, Shell, St } = imports.gi; ++const Signals = imports.signals; + + const ExtensionUtils = imports.misc.extensionUtils; + const Main = imports.ui.main; ++const MessageList = imports.ui.messageList; + const Tweener = imports.ui.tweener; + + const Gettext = imports.gettext.domain('gnome-shell-extensions'); +@@ -21,22 +23,25 @@ const ITEM_HOVER_TIMEOUT = 300; + const Indicator = class { + constructor() { + this._initValues(); +- this._drawingArea = new St.DrawingArea({ reactive: true }); ++ this._drawingArea = new St.DrawingArea(); + this._drawingArea.connect('repaint', this._draw.bind(this)); +- this._drawingArea.connect('button-press-event', () => { ++ ++ this.actor = new St.Button({ ++ style_class: 'message message-content extension-systemMonitor-indicator-area', ++ child: this._drawingArea, ++ x_expand: true, ++ x_fill: true, ++ y_fill: true, ++ can_focus: true ++ }); ++ ++ this.actor.connect('clicked', () => { + let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop'); + app.open_new_window(-1); +- return true; +- }); + +- this.actor = new St.Bin({ +- style_class: 'extension-systemMonitor-indicator-area', +- reactive: true, +- track_hover: true, +- x_fill: true, +- y_fill: true ++ Main.overview.hide(); ++ Main.panel.closeCalendar(); + }); +- this.actor.add_actor(this._drawingArea); + + this.actor.connect('destroy', this._onDestroy.bind(this)); + +@@ -71,6 +76,7 @@ const Indicator = class { + let y = stageY - this.label.get_height() - yOffset; + + this.label.set_position(x, y); ++ this.label.get_parent().set_child_above_sibling(this.label, null); + Tweener.addTween(this.label, { + opacity: 255, + time: ITEM_LABEL_SHOW_TIME, +@@ -98,6 +104,14 @@ const Indicator = class { + }); + } + ++ /* MessageList.Message boilerplate */ ++ canClose() { ++ return false; ++ } ++ ++ clear() { ++ } ++ + destroy() { + this.actor.destroy(); + } +@@ -195,6 +209,7 @@ const Indicator = class { + } + } + }; ++Signals.addSignalMethods(Indicator.prototype); // For MessageList.Message compat + + const CpuIndicator = class extends Indicator { + constructor() { +@@ -300,11 +315,7 @@ class Extension { + } + + enable() { +- this._box = new St.BoxLayout({ +- style_class: 'extension-systemMonitor-container', +- x_align: Clutter.ActorAlign.START, +- x_expand: true +- }); ++ this._section = new MessageList.MessageListSection(_('System Monitor')); + this._indicators = []; + + for (let i = 0; i < INDICATORS.length; i++) { +@@ -313,32 +324,18 @@ class Extension { + indicator.actor.connect('notify::hover', () => { + this._onHover(indicator); + }); +- this._box.add_actor(indicator.actor); ++ this._section.addMessage(indicator, false); + this._indicators.push(indicator); + } + +- this._boxHolder = new St.BoxLayout({ +- x_expand: true, +- y_expand: true, +- x_align: Clutter.ActorAlign.START, +- }); +- let menuButton = Main.messageTray._messageTrayMenuButton.actor; +- Main.messageTray.actor.remove_child(menuButton); +- Main.messageTray.actor.add_child(this._boxHolder); +- +- this._boxHolder.add_child(this._box); +- this._boxHolder.add_child(menuButton); ++ Main.panel.statusArea.dateMenu._messageList._addSection(this._section); ++ this._section.actor.get_parent().set_child_at_index(this._section.actor, 0); + } + + disable() { + this._indicators.forEach(i => i.destroy()); + +- let menuButton = Main.messageTray._messageTrayMenuButton.actor; +- this._boxHolder.remove_child(menuButton); +- Main.messageTray.actor.add_child(menuButton); +- +- this._box.destroy(); +- this._boxHolder.destroy(); ++ Main.panel.statusArea.dateMenu._messageList._removeSection(this._section); + } + + _onHover(item) { +diff --git a/extensions/systemMonitor/stylesheet.css b/extensions/systemMonitor/stylesheet.css +index 13f95ec..978ac12 100644 +--- a/extensions/systemMonitor/stylesheet.css ++++ b/extensions/systemMonitor/stylesheet.css +@@ -1,17 +1,4 @@ +-.extension-systemMonitor-container { +- spacing: 5px; +- padding-left: 5px; +- padding-right: 5px; +- padding-bottom: 10px; +- padding-top: 10px; +-} +- + .extension-systemMonitor-indicator-area { +- border: 1px solid #8d8d8d; +- border-radius: 3px; +- width: 100px; +- /* message tray is 72px, so 20px padding of the container, +- 2px of border, makes it 50px */ + height: 50px; + -grid-color: #575757; + -cpu-total-color: rgb(0,154,62); +@@ -21,7 +8,6 @@ + -mem-user-color: rgb(210,148,0); + -mem-cached-color: rgb(90,90,90); + -mem-other-color: rgb(205,203,41); +- background-color: #1e1e1e; + } + + .extension-systemMonitor-indicator-label { +-- +2.21.0 + + +From f73fe9cfb5f9dbd6647e4eb30a9af0fb7ff79219 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 18 May 2017 16:20:07 +0200 +Subject: [PATCH 4/5] systemMonitor: Handle clicks on section title + +While on 3.24.x only the event section still has a clickable title, +it's a generic message list feature in previous versions. It's easy +enough to support with a small subclass, so use that instead of +the generic baseclass. + +Fixes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions3 +--- + extensions/systemMonitor/extension.js | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js +index 0188960..b4d5a9d 100644 +--- a/extensions/systemMonitor/extension.js ++++ b/extensions/systemMonitor/extension.js +@@ -303,6 +303,21 @@ const MemoryIndicator = class extends Indicator { + } + }; + ++class SystemMonitorSection extends MessageList.MessageListSection { ++ constructor() { ++ super(_('System Monitor')); ++ } ++ ++ _onTitleClicked() { ++ super._onTitleClicked(); ++ ++ let appSys = Shell.AppSystem.get_default(); ++ let app = appSys.lookup_app('gnome-system-monitor.desktop'); ++ if (app) ++ app.open_new_window(-1); ++ } ++} ++ + const INDICATORS = [CpuIndicator, MemoryIndicator]; + + class Extension { +@@ -315,7 +330,7 @@ class Extension { + } + + enable() { +- this._section = new MessageList.MessageListSection(_('System Monitor')); ++ this._section = new SystemMonitorSection(); + this._indicators = []; + + for (let i = 0; i < INDICATORS.length; i++) { +-- +2.21.0 + + +From df76e98d6bbac7dccc86f66e82eac2977fb5ed87 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 18 May 2017 18:00:17 +0200 +Subject: [PATCH 5/5] systemMonitor: Provide classic styling + +The indicator tooltips currently don't work out in classic mode +(dark text on dark background), so provide some mode-specific +style. + +Fixes: #4 +--- + extensions/systemMonitor/classic.css | 6 ++++++ + extensions/systemMonitor/meson.build | 4 ++++ + 2 files changed, 10 insertions(+) + create mode 100644 extensions/systemMonitor/classic.css + +diff --git a/extensions/systemMonitor/classic.css b/extensions/systemMonitor/classic.css +new file mode 100644 +index 0000000..946863d +--- /dev/null ++++ b/extensions/systemMonitor/classic.css +@@ -0,0 +1,6 @@ ++@import url("stylesheet.css"); ++ ++.extension-systemMonitor-indicator-label { ++ background-color: rgba(237,237,237,0.9); ++ border: 1px solid #a1a1a1; ++} +diff --git a/extensions/systemMonitor/meson.build b/extensions/systemMonitor/meson.build +index 48504f6..b6548b1 100644 +--- a/extensions/systemMonitor/meson.build ++++ b/extensions/systemMonitor/meson.build +@@ -3,3 +3,7 @@ extension_data += configure_file( + output: metadata_name, + configuration: metadata_conf + ) ++ ++if classic_mode_enabled ++ extension_data += files('classic.css') ++endif +-- +2.21.0 + diff --git a/SOURCES/window-list-touch.patch b/SOURCES/window-list-touch.patch new file mode 100644 index 0000000..b47741c --- /dev/null +++ b/SOURCES/window-list-touch.patch @@ -0,0 +1,126 @@ +From f8ec838485ae81cf2e8ab2b899ad4154c7c06fbd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 21 Apr 2022 16:34:50 +0200 +Subject: [PATCH 1/2] window-list: Fix primary button action on touch + +If a click event was triggered via touch rather than a pointer +device, the button parameter is 0 rather than a mouse button +number. + +Account for that to make sure that touch events are not misinterpreted +as right clicks. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/146 + +Part-of: +--- + extensions/window-list/extension.js | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js +index 1f854aa2..fedc4195 100644 +--- a/extensions/window-list/extension.js ++++ b/extensions/window-list/extension.js +@@ -358,7 +358,7 @@ class WindowButton extends BaseButton { + return; + } + +- if (button == 1) ++ if (!button || button === 1) + _minimizeOrActivateWindow(this.metaWindow); + else + _openMenu(this._contextMenu); +@@ -601,7 +601,7 @@ class AppButton extends BaseButton { + if (contextMenuWasOpen) + this._contextMenu.close(); + +- if (button == 1) { ++ if (!button || button === 1) { + if (menuWasOpen) + return; + +-- +2.36.1 + + +From d3cf07f8065935736e8a79d06ec79c971c453453 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 5 May 2022 20:55:20 +0200 +Subject: [PATCH 2/2] window-list: Open menu on long press + +Right-click isn't available on touch, so implement long-press as +an alternative. + +https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/146 + +Part-of: +--- + extensions/window-list/extension.js | 45 +++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/extensions/window-list/extension.js b/extensions/window-list/extension.js +index fedc4195..0baaeecb 100644 +--- a/extensions/window-list/extension.js ++++ b/extensions/window-list/extension.js +@@ -229,6 +229,9 @@ class BaseButton { + this.actor.connect('clicked', this._onClicked.bind(this)); + this.actor.connect('destroy', this._onDestroy.bind(this)); + this.actor.connect('popup-menu', this._onPopupMenu.bind(this)); ++ this.actor.connect('button-press-event', this._onButtonPress.bind(this)); ++ this.actor.connect('button-release-event', this._onButtonRelease.bind(this)); ++ this.actor.connect('touch-event', this._onTouch.bind(this)); + + this._contextMenuManager = new PopupMenu.PopupMenuManager(this); + +@@ -250,6 +253,48 @@ class BaseButton { + return this.actor.has_style_class_name('focused'); + } + ++ _setLongPressTimeout() { ++ if (this._longPressTimeoutId) ++ return; ++ ++ const { longPressDuration } = Clutter.Settings.get_default(); ++ this._longPressTimeoutId = ++ GLib.timeout_add(GLib.PRIORITY_DEFAULT, longPressDuration, () => { ++ delete this._longPressTimeoutId; ++ ++ if (this._canOpenPopupMenu() && !this._contextMenu.isOpen) ++ _openMenu(this._contextMenu); ++ return GLib.SOURCE_REMOVE; ++ }); ++ } ++ ++ _removeLongPressTimeout() { ++ if (!this._longPressTimeoutId) ++ return; ++ GLib.source_remove(this._longPressTimeoutId); ++ delete this._longPressTimeoutId; ++ } ++ ++ _onButtonPress(button, event) { ++ if (event.get_button() === 1) ++ this._setLongPressTimeout(); ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _onButtonRelease() { ++ this._removeLongPressTimeout(); ++ return Clutter.EVENT_PROPAGATE; ++ } ++ ++ _onTouch(event) { ++ const type = event.get_type(); ++ if (type === Clutter.EventType.TOUCH_BEGIN) ++ this._setLongPressTimeout(); ++ else if (type === Clutter.EventType.TOUCH_END) ++ this._removeLongPressTimeout(); ++ return Clutter.EVENT_PROPAGATE; ++ } ++ + activate() { + if (this.active) + return; +-- +2.36.1 + diff --git a/SPECS/gnome-shell-extensions.spec b/SPECS/gnome-shell-extensions.spec new file mode 100644 index 0000000..3768c78 --- /dev/null +++ b/SPECS/gnome-shell-extensions.spec @@ -0,0 +1,1209 @@ +%global major_version %%(cut -d "." -f 1-2 <<<%{version}) +# Minimum GNOME Shell version supported +%global min_gs_version %%(cut -d "." -f 1-3 <<<%{version}) + +%global pkg_prefix gnome-shell-extension + +Name: gnome-shell-extensions +Version: 3.32.1 +Release: 33%{?dist} +Summary: Modify and extend GNOME Shell functionality and behavior + +Group: User Interface/Desktops +License: GPLv2+ +URL: http://wiki.gnome.org/Projects/GnomeShell/Extensions +Source0: http://ftp.gnome.org/pub/GNOME/sources/%{name}/%{major_version}/%{name}-%{version}.tar.xz +Source1: gnome-classic.desktop +Source2: gnome-classic-wayland.desktop + +# BuildRequires: gnome-common +BuildRequires: meson +BuildRequires: sassc +BuildRequires: git +BuildRequires: gettext >= 0.19.6 +BuildRequires: pkgconfig(gnome-desktop-3.0) +BuildRequires: pkgconfig(libgtop-2.0) +Requires: gnome-shell >= %{min_gs_version} +BuildArch: noarch + +Patch0001: 0001-Update-style.patch +Patch0002: 0001-apps-menu-add-logo-icon-to-Applications-menu.patch +Patch0003: add-extra-extensions.patch +Patch0004: 0001-apps-menu-Explicitly-set-label_actor.patch +Patch0005: resurrect-system-monitor.patch +Patch0006: 0001-Include-top-icons-in-classic-session.patch +Patch0007: more-classic-classic-mode.patch +Patch0008: 0001-apps-menu-Add-missing-chain-up.patch +Patch0009: 0001-dashToDock-Handle-no-overview-case.patch +Patch0010: 0001-window-list-Invalid-current-mode-selected-in-Prefere.patch +Patch0011: 0001-Update-desktop-icons-gettext-domain.patch +Patch0012: 0001-desktop-icons-Update-Japanese-translation.patch +Patch0013: 0001-fileItem-Ignore-double-click-distance-clicking-on-it.patch +Patch0014: 0001-window-list-Leave-fake-overview-when-destroyed.patch +Patch0015: add-workspace-tooltips.patch +Patch0016: 0001-general-launch-only-executable-files.patch +Patch0017: desktop-icons-touch-support.patch +Patch0018: 0001-Add-gesture-inhibitor-extension.patch +Patch0019: 0001-top-icons-Don-t-use-wm_class-as-role.patch +Patch0020: 0001-heads-up-display-Add-extension-for-showing-persisten.patch +Patch0021: 0001-desktop-icons-Fix-stuck-grab-issue-with-rubber-bandi.patch +Patch0022: 0001-gesture-inhibitor-Put-a-foot-down-with-self-enabling.patch +Patch0023: 0001-desktop-icons-Use-a-single-unique-name-to-access-nau.patch +Patch0024: window-list-touch.patch +Patch0025: 0001-auto-move-windows-Don-t-move-windows-already-on-all-.patch +Patch0026: 0001-fileItem-Just-destroy-menus.patch +Patch0027: 0001-fileItem-Support-.desktop-files-of-type-Link.patch +Patch0028: 0001-classification-banner-Handle-fullscreen-monitors.patch +Patch0029: 0001-gesture-inhibitor-Allow-inhibiting-workspace-switch-.patch +Patch0030: 0001-desktop-icons-Don-t-use-blocking-IO.patch + +%description +GNOME Shell Extensions is a collection of extensions providing additional and +optional functionality to GNOME Shell. + +Enabled extensions: + * apps-menu + * auto-move-windows + * classification-banner + * custom-menu + * dash-to-dock + * dash-to-panel + * disable-screenshield + * desktop-icons + * gesture-inhibitor + * heads-up-display + * horizontal-workspaces + * drive-menu + * launch-new-instance + * native-window-placement + * no-hot-corner + * panel-favorites + * places-menu + * screenshot-window-sizer + * top-icons + * updates-dialog + * user-theme + * window-list + * windowsNavigator + * workspace-indicator + + +%package -n %{pkg_prefix}-common +Summary: Files common to GNOME Shell Extensions +Group: User Interface/Desktops +License: GPLv2+ +Requires: gnome-shell >= %{min_gs_version} +# Dock extension no longer provided by GNOME Shell extensions >= 3.7.1 +Obsoletes: %{pkg_prefix}-dock < 3.7.1 +Obsoletes: %{pkg_prefix}-alternate-tab < 3.31.2 +# Alternative-status-menu extension no longer provided by GNOME Shell extensions >= 3.9.5 +Obsoletes: %{pkg_prefix}-alternative-status-menu < 3.9.5 +# Xrandr-indicator extension no longer provided by GNOME Shell extensions >= 3.9.5 +Obsoletes: %{pkg_prefix}-xrandr-indicator < 3.9.90 +# Obsolete extensions dropped in favor of schema overrides by upstream +Obsoletes: %{pkg_prefix}-default-min-max < 3.9.3-1 +Obsoletes: %{pkg_prefix}-static-workspaces < 3.9.3-1 +Obsoletes: %{pkg_prefix}-systemMonitor < 3.15.91 + +%description -n %{pkg_prefix}-common +GNOME Shell Extensions is a collection of extensions providing additional and +optional functionality to GNOME Shell. + +This package provides common data files shared by various extensions. + + +%package -n gnome-classic-session +Summary: GNOME "classic" mode session +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-apps-menu = %{version}-%{release} +Requires: %{pkg_prefix}-desktop-icons = %{version}-%{release} +Requires: %{pkg_prefix}-horizontal-workspaces = %{version}-%{release} +Requires: %{pkg_prefix}-launch-new-instance = %{version}-%{release} +Requires: %{pkg_prefix}-places-menu = %{version}-%{release} +Requires: %{pkg_prefix}-window-list = %{version}-%{release} +Requires: nautilus +# Obsolete fallback mode components +Obsoletes: gnome-applets < 1:3.5.92-5 +%global gnome_applet_sensors_obsolete_ver 3.0.0-6 +Obsoletes: gnome-applet-sensors < %{gnome_applet_sensors_obsolete_ver} +Obsoletes: gnome-applet-sensors-devel < %{gnome_applet_sensors_obsolete_ver} +%global gnome_panel_obsolete_ver 3.6.2-7 +Obsoletes: gnome-panel < %{gnome_panel_obsolete_ver} +Obsoletes: gnome-panel-devel < %{gnome_panel_obsolete_ver} +Obsoletes: gnome-panel-libs < %{gnome_panel_obsolete_ver} + +%description -n gnome-classic-session +This package contains the required components for the GNOME Shell "classic" +mode, which aims to provide a GNOME 2-like user interface. + + +%package -n %{pkg_prefix}-apps-menu +Summary: Application menu for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} +Requires: gnome-menus + +%description -n %{pkg_prefix}-apps-menu +This GNOME Shell extension adds a GNOME 2.x style menu for applications. + + +%package -n %{pkg_prefix}-auto-move-windows +Summary: Assign specific workspaces to applications in GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-auto-move-windows +This GNOME Shell extension enables easy workspace management. A specific +workspace can be assigned to each application as soon as it creates a window, in +a manner configurable with a GSettings key. + + +%package -n %{pkg_prefix}-classification-banner +Summary: Display classification level banner in GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-classification-banner +This GNOME Shell extension adds a banner that displays the classification level. + + +%package -n %{pkg_prefix}-custom-menu +Summary: Add a custom menu to the desktop +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-custom-menu +This GNOME Shell extension adds a custom menu to the desktop background. + + +%package -n %{pkg_prefix}-dash-to-dock +Summary: Show the dash outside the activities overview +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-dash-to-dock +This GNOME Shell extension makes the dash available outside the activities overview. + + +%package -n %{pkg_prefix}-dash-to-panel +Summary: Show the dash in the top bar +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-dash-to-panel +This GNOME Shell extension makes the dash available in the top bar + + +%package -n %{pkg_prefix}-disable-screenshield +Summary: Disable GNOME Shell screen shield if lock is disabled +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-disable-screenshield +This GNOME Shell extension disabled the screen shield if screen locking is disabled. + + +%package -n %{pkg_prefix}-heads-up-display +Summary: Display persistent on-screen message +Group: User Interface/Desktops +License: GPLv3+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-heads-up-display +This GNOME Shell extension displays a persistent message in the top middle of the screen. +This message can appear on the login screen, lock screen, or regular user session. + + +%package -n %{pkg_prefix}-horizontal-workspaces +Summary: Desktop icons support for the classic experience +Group: User Interface/Desktops +License: GPLv3+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-horizontal-workspaces +This GNOME Shell extension adds desktop icons support as seen in GNOME 2 + + +%package -n %{pkg_prefix}-desktop-icons +Summary: Desktop icons support for the classic experience +Group: User Interface/Desktops +License: GPLv3+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-desktop-icons +This GNOME Shell extension adds desktop icons support as seen in GNOME 2 + + +%package -n %{pkg_prefix}-drive-menu +Summary: Drive status menu for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-drive-menu +This GNOME Shell extension provides a panel status menu for accessing and +unmounting removable devices. + + +%package -n %{pkg_prefix}-gesture-inhibitor +Summary: Gesture inhibitor +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-gesture-inhibitor +This GNOME Shell extension allows disabling the default desktop gestures. + + +%package -n %{pkg_prefix}-launch-new-instance +Summary: Always launch a new application instance for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-launch-new-instance +This GNOME Shell extension modifies the behavior of clicking in the dash and app +launcher to always launch a new application instance. + + +%package -n %{pkg_prefix}-native-window-placement +Summary: Native window placement for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-native-window-placement +This GNOME Shell extension provides additional configurability for the window +layout in the overview, including a mechanism similar to KDE4. + + +%package -n %{pkg_prefix}-no-hot-corner +Summary: Disable the hot corner in GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-no-hot-corner +This GNOME Shell extension disables the hot corner in the top bar. + + +%package -n %{pkg_prefix}-panel-favorites +Summary: Favorite launchers in GNOME Shell's top bar +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-panel-favorites +This GNOME Shell extension adds favorite launchers to the top bar. + + +%package -n %{pkg_prefix}-places-menu +Summary: Places status menu for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-places-menu +This GNOME Shell extension add a system status menu for quickly navigating +places in the system. + + +%package -n %{pkg_prefix}-screenshot-window-sizer +Summary: Screenshot window sizer for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-screenshot-window-sizer +This GNOME Shell extension allows to easily resize windows for GNOME Software +screenshots. + + +%package -n %{pkg_prefix}-systemMonitor +Summary: System Monitor for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} +# Should be pulled in by control-center, but in case someone tries for a +# minimalist gnome-shell installation +Requires: libgtop2 + +%description -n %{pkg_prefix}-systemMonitor +This GNOME Shell extension is a message tray indicator for CPU and memory usage + + +%package -n %{pkg_prefix}-top-icons +Summary: Show legacy icons on top +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-top-icons +This GNOME Shell extension moves legacy tray icons into the top bar. + + +%package -n %{pkg_prefix}-updates-dialog +Summary: Show a modal dialog when there are software updates +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-updates-dialog +This GNOME Shell extension shows a modal dialog when there are software updates + + +%package -n %{pkg_prefix}-user-theme +Summary: Support for custom themes in GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-user-theme +This GNOME Shell extension enables loading a GNOME Shell theme from +~/.themes//gnome-shell/. + + +%package -n %{pkg_prefix}-window-grouper +Summary: Keep windows that belong to the same process on the same workspace +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-window-grouper +This GNOME Shell extension keeps windows that belong to the same process on the same workspace. + + +%package -n %{pkg_prefix}-window-list +Summary: Display a window list at the bottom of the screen in GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-window-list +This GNOME Shell extension displays a window list at the bottom of the screen. + + +%package -n %{pkg_prefix}-windowsNavigator +Summary: Support for keyboard selection of windows and workspaces in GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-windowsNavigator +This GNOME Shell extension enables keyboard selection of windows and workspaces +in overlay mode, by pressing the Alt and Ctrl key respectively. + + +%package -n %{pkg_prefix}-workspace-indicator +Summary: Workspace indicator for GNOME Shell +Group: User Interface/Desktops +License: GPLv2+ +Requires: %{pkg_prefix}-common = %{version}-%{release} + +%description -n %{pkg_prefix}-workspace-indicator +This GNOME Shell extension add a system status menu for quickly changing +workspaces. + + +%prep +%autosetup -S git + + +%build +%meson -Dextension_set="all" -Dclassic_mode=true +%meson_build + + +%install +%meson_install + +# rename GNOME Classic to Classic and provide a wayland variant +mkdir -p $RPM_BUILD_ROOT%{_datadir}/wayland-sessions +cp $RPM_BUILD_ROOT%{_datadir}/xsessions/gnome-classic.desktop \ + $RPM_BUILD_ROOT%{_datadir}/wayland-sessions/gnome-classic-wayland.desktop + +cp $RPM_SOURCE_DIR/gnome-classic-wayland.desktop $RPM_BUILD_ROOT%{_datadir}/wayland-sessions +cp $RPM_SOURCE_DIR/gnome-classic.desktop $RPM_BUILD_ROOT%{_datadir}/xsessions + +%find_lang %{name} + + +%files -n %{pkg_prefix}-common -f %{name}.lang +%doc NEWS README.md +%license COPYING + + +%files -n gnome-classic-session +%{_datadir}/gnome-session/sessions/gnome-classic.session +%{_datadir}/gnome-shell/modes/classic.json +%{_datadir}/gnome-shell/theme/*.svg +%{_datadir}/gnome-shell/theme/gnome-classic-high-contrast.css +%{_datadir}/gnome-shell/theme/gnome-classic.css +%{_datadir}/xsessions/gnome-classic.desktop +%{_datadir}/wayland-sessions/gnome-classic-wayland.desktop +%{_datadir}/glib-2.0/schemas/00_org.gnome.shell.extensions.classic.gschema.override + +%files -n %{pkg_prefix}-apps-menu +%{_datadir}/gnome-shell/extensions/apps-menu*/ + + +%files -n %{pkg_prefix}-auto-move-windows +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.auto-move-windows.gschema.xml +%{_datadir}/gnome-shell/extensions/auto-move-windows*/ + + +%files -n %{pkg_prefix}-classification-banner +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.classification-banner.gschema.xml +%{_datadir}/gnome-shell/extensions/classification-banner*/ + + +%files -n %{pkg_prefix}-custom-menu +%{_datadir}/gnome-shell/extensions/custom-menu*/ + + +%files -n %{pkg_prefix}-dash-to-dock +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.dash-to-dock.gschema.xml +%{_datadir}/gnome-shell/extensions/dash-to-dock*/ + + +%files -n %{pkg_prefix}-dash-to-panel +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.dash-to-panel.gschema.xml +%{_datadir}/gnome-shell/extensions/dash-to-panel*/ + + +%files -n %{pkg_prefix}-disable-screenshield +%{_datadir}/gnome-shell/extensions/disable-screenshield*/ + + +%files -n %{pkg_prefix}-heads-up-display +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.heads-up-display.gschema.xml +%{_datadir}/gnome-shell/extensions/heads-up-display*/ + + +%files -n %{pkg_prefix}-horizontal-workspaces +%{_datadir}/gnome-shell/extensions/horizontal-workspaces*/ + + +%files -n %{pkg_prefix}-desktop-icons +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.desktop-icons.gschema.xml +%{_datadir}/gnome-shell/extensions/desktop-icons*/ + + +%files -n %{pkg_prefix}-drive-menu +%{_datadir}/gnome-shell/extensions/drive-menu*/ + + +%files -n %{pkg_prefix}-gesture-inhibitor +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.gesture-inhibitor.gschema.xml +%{_datadir}/gnome-shell/extensions/gesture-inhibitor*/ + + +%files -n %{pkg_prefix}-launch-new-instance +%{_datadir}/gnome-shell/extensions/launch-new-instance*/ + + +%files -n %{pkg_prefix}-native-window-placement +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.native-window-placement.gschema.xml +%{_datadir}/gnome-shell/extensions/native-window-placement*/ + + +%files -n %{pkg_prefix}-no-hot-corner +%{_datadir}/gnome-shell/extensions/no-hot-corner*/ + + +%files -n %{pkg_prefix}-panel-favorites +%{_datadir}/gnome-shell/extensions/panel-favorites*/ + + +%files -n %{pkg_prefix}-places-menu +%{_datadir}/gnome-shell/extensions/places-menu*/ + + +%files -n %{pkg_prefix}-screenshot-window-sizer +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml +%{_datadir}/gnome-shell/extensions/screenshot-window-sizer*/ + + +%files -n %{pkg_prefix}-systemMonitor +%{_datadir}/gnome-shell/extensions/systemMonitor*/ + + +%files -n %{pkg_prefix}-top-icons +%{_datadir}/gnome-shell/extensions/top-icons*/ + + +%files -n %{pkg_prefix}-updates-dialog +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.updates-dialog.gschema.xml +%{_datadir}/gnome-shell/extensions/updates-dialog*/ + + +%files -n %{pkg_prefix}-user-theme +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.user-theme.gschema.xml +%{_datadir}/gnome-shell/extensions/user-theme*/ + + +%files -n %{pkg_prefix}-window-grouper +%{_datadir}/gnome-shell/extensions/window-grouper*/ +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.window-grouper.gschema.xml + + +%files -n %{pkg_prefix}-window-list +%{_datadir}/gnome-shell/extensions/window-list*/ +%{_datadir}/glib-2.0/schemas/org.gnome.shell.extensions.window-list.gschema.xml + + +%files -n %{pkg_prefix}-windowsNavigator +%{_datadir}/gnome-shell/extensions/windowsNavigator*/ + + +%files -n %{pkg_prefix}-workspace-indicator +%{_datadir}/gnome-shell/extensions/workspace-indicator*/ + + +%changelog +* Tue Jan 17 2023 Florian Müllner - 3.32.1-33 +- Avoid blocking IO in desktop-icons + Resolves: #2162017 + +* Thu Jan 12 2023 Florian Müllner - 3.32.1-32 +- Add custom-menu extension + Resolves: #2033572 + +* Wed Dec 14 2022 Florian Müllner - 3.32.1-31 +- Adjust classification banner position in fullscreen + Resolves: #2150107 +- Allow inhibiting workspace switch gesture + Resolves: #2138109 + +* Fri Dec 09 2022 Florian Müllner - 3.32.1-30 +- Fix stuck grab if disabled with open context menu + Resolves: #2149670 +- Support .desktop files of type Link + Resolves: #2143825 + +* Mon Aug 29 2022 Jonas Ådahl - 3.32.1-29 +- Avoid invalid window management in auto-move-windows + Resolves: #2089311 + +* Wed Jun 22 2022 Florian Müllner - 3.32.1-28 +- Improve window-list on touch + Resolves: #2050000 + +* Tue Dec 14 2021 Florian Müllner - 3.32.1-27 +- Keep classification banners on login/lock screen + Resolves: #1751336 + +* Fri Dec 10 2021 Florian Müllner - 3.32.1-26 +- Add classification-banner + Resolves: #1751336 + +* Mon Nov 29 2021 Florian Müllner - 3.32.1-25 +- Fix desktop-icons warning + Resolves: #2026622 + +* Thu Nov 04 2021 Carlos Garnacho - 3.32.1-24 +- Fix gesture inhibitor extension with unfullscreen gesture + Resolves: #1988906 + +* Tue Nov 02 2021 Jonas Ådahl - 3.32.1-23 +- Fix stuck grab on desktop-icons + Resolves: #1984956 + +* Tue Oct 19 2021 Florian Müllner - 3.32.1-22 +- Install missing prefs file + Related: #1995814 + +* Mon Oct 18 2021 Florian Müllner - 3.32.1-21 +- Add dash-to-panel + Resolves: #1995814 + +* Thu Aug 26 2021 Ray Strode - 3.32.1-20 +- Add extension for displaying heads up message + Related: #1651378 + +* Wed Jun 02 2021 Florian Müllner - 3.32.1-19 +- Don't use status icon wm_class as top bar role + Resolves: #1897932 + +* Tue Jun 01 2021 Carlos Garnacho - 3.32.1-18 +- Add gesture-inhibitor extension + Resolves: #1854679 + +* Tue Jun 01 2021 Carlos Garnacho - 3.32.1-17 +- Handle touchscreens on Wayland in the desktop-icons extension + Resolves: #1924725 + +* Mon May 31 2021 Florian Müllner - 3.32.1-16 +- Fix opening files with (wrongly) set executable bit + Resolves: #1813727 + +* Tue Apr 13 2021 Florian Müllner - 3.32.1-15 +- Fix stuck window picker after screen lock + Resolves: #1905000 +- Add tooltips to workspace previews + Resolves: #1894613 + +* Wed Jan 27 2021 Carlos Garnacho - 3.32.1-14 +- Use same logic than Nautilus for double click/tap in desktop-icons extension + Resolves: #1842229 + +* Wed Jan 27 2021 Florian Müllner - 3.32.1-13 +- Update Japanese translation + Related: #1865718 + +* Sat Oct 24 2020 Florian Müllner - 3.32.1-12 +- Adjust gettext locale in desktop-icons extension + Resolves: #1865718 + +* Thu Apr 30 2020 Florian Müllner - 3.32.1-11 +- Adjust dash-to-dock for classic backports + Resolves: #1805929 +- Fix inconsistent state in window-list prefs dialog + Resolves: #1824362 + +* Wed Jul 24 2019 Florian Müllner - 3.32.1-10 +- Drop obsolete downstream style patch +- Keep classic notification styling + Related: #1731372 + +* Thu Jul 18 2019 Florian Müllner - 3.32.1-9 +- Backport classic style improvements + Resolves: #1726093 + +* Thu Jul 04 2019 Florian Müllner - 3.32.1-8 +- Allow closing window picker with Escape + Resolves: #1725854 + +* Sat Jun 29 2019 Florian Müllner - 3.32-1-7 +- Add window thumbnails to workspace switcher + Resolves: #1723467 +- Fix apps-menu not disabling itself entirely + Resolves: #1722047 + +* Tue Jun 25 2019 Florian Müllner - 3.32-1-6 +- Fix new classic mode issues: + - stray signal handler with overlay key + Resolves: #1722844 + - improve DND support: + + don't consider regular windows + (it doesn't work well, and GNOME 2 didn't support it either) + + indicate that workspace thumbs are drop targets + Related: #1704360 + +* Tue Jun 18 2019 Florian Müllner - 3.32.1-5 +- Small refinements after design feedback: + - use default icon size in picker button to avoid blurriness + - use shortcut to open window picker + Resolves: #1721195 + +* Tue Jun 18 2019 Florian Müllner - 3.32.1-4 +- Don't add apps-menu logo when activities button is present + Resolves: #1721195 + +* Wed Jun 12 2019 Florian Müllner - 3.32.1-3 +- Make classic mode more classic + Resolves: #1704360 + +* Fri May 31 2019 Florian Müllner - 3.32.1-2 +- Fix top-icons sizing issue + Resolves: #1715765 + +* Thu May 23 2019 Florian Müllner - 3.32.1-1 +- Update to 3.32.1 + Resolves: #1713453 + +* Mon Feb 11 2019 Florian Müllner - 3.28.1-8 +- Update desktop-icons extension to 19.01 + Resolves: #1666739 + +* Fri Feb 08 2019 Florian Müllner - 3.28.1-7 +- Re-add dropped downstream patches + Resolves: #1668885 + +* Mon Jan 14 2019 Ray Strode - 3.28.1-6 +- Update desktop file names + Related: #1647713 + +* Thu Dec 06 2018 Ray Strode - 3.28.1-5 +- Add requires on desktop-icons extension for classic session + Resolves: #1648863 + +* Tue Sep 04 2018 Ray Strode - 3.28.1-4 +- Add back corporate logo on the left of Activities +- Remove shadow remnants of app logo to the right of Activities + Resolves: #1620241 + +* Wed Aug 22 2018 Ray Strode - 3.28.1-3 +- Add a wayland variant of gnome-classic + Also change up the names to Standard and Classic to match UX design + + Related: #1612915 1595825 + +* Tue Aug 21 2018 Carlos Soriano - 3.28.1-2 +- Add desktop icons extension + +* Fri Apr 13 2018 Florian Müllner - 3.28.1-1 +- Update to 3.28.1 + +* Mon Mar 12 2018 Florian Müllner - 3.28.0-1 +- Update to 3.28.0 + +* Mon Mar 05 2018 Florian Müllner - 3.27.92-1 +- Update to 3.27.92 + +* Thu Feb 22 2018 Florian Müllner - 3.27.91-1 +- Update to 3.27.91 + +* Wed Feb 07 2018 Fedora Release Engineering - 3.27.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Jan 06 2018 Igor Gnatenko - 3.27.1-2 +- Remove obsolete scriptlets + +* Tue Oct 17 2017 Florian Müllner - 3.27.1-1 +- Update to 3.27.1 + +* Wed Oct 04 2017 Florian Müllner - 3.26.1-1 +- Update to 3.26.1 + +* Tue Sep 12 2017 Florian Müllner - 3.26.0-1 +- Update to 3.26.0 + +* Tue Aug 22 2017 Florian Müllner - 3.25.91-1 +- Update to 3.25.91 + +* Fri Aug 11 2017 Kevin Fenzi - 3.25.90-2 +- Rebuild with older working rpm + +* Thu Aug 10 2017 Florian Müllner - 3.25.90-1 +- Update to 3.25.90 + +* Wed Jul 26 2017 Fedora Release Engineering - 3.25.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Jul 20 2017 Florian Müllner - 3.25.4-1 +- Update to 3.25.4 + +* Wed Jun 21 2017 Florian Müllner - 3.25.3-1 +- Update to 3.25.3 + +* Thu May 25 2017 Florian Müllner - 3.25.2-1 +- Update to 3.25.2 + +* Thu Apr 27 2017 Florian Müllner - 3.25.1-1 +- Update to 3.25.1 + +* Tue Apr 11 2017 Florian Müllner - 3.24.1-1 +- Update to 3.24.1 + +* Mon Mar 20 2017 Florian Müllner - 3.24.0-1 +- Update to 3.24.0 + +* Tue Mar 14 2017 Florian Müllner - 3.23.92-1 +- Update to 3.23.92 + +* Wed Mar 01 2017 Florian Müllner - 3.23.91-1 +- Update to 3.23.91 + +* Thu Feb 16 2017 Florian Müllner - 3.23.90-1 +- Update to 3.23.90 + +* Fri Feb 10 2017 Fedora Release Engineering - 3.23.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Wed Nov 23 2016 Florian Müllner - 3.23.2-1 +- Update to 3.23.2 + +* Tue Oct 11 2016 Florian Müllner - 3.22.1-1 +- Update to 3.22.1 + +* Mon Sep 19 2016 Florian Müllner - 3.22.0-1 +- Update to 3.22.0 + +* Tue Sep 13 2016 Florian Müllner - 3.21.92-1 +- Update to 3.21.92 + +* Tue Aug 30 2016 Florian Müllner - 3.21.91-1 +- Update to 3.21.91 + +* Fri Aug 19 2016 Florian Müllner - 3.21.90-1 +- Update to 3.21.90 + +* Wed Jul 20 2016 Florian Müllner - 3.21.4-1 +- Update to 3.21.4 + +* Tue Jun 21 2016 Florian Müllner - 3.21.3-1 +- Update to 3.21.3 + +* Fri May 27 2016 Florian Müllner - 3.21.2-1 +- Update to 3.21.2 + +* Tue May 10 2016 Florian Müllner - 3.20.1-1 +- Update to 3.20.1 + +* Tue Mar 22 2016 Florian Müllner - 3.20.0-1 +- Update to 3.20.0 + +* Wed Mar 16 2016 Florian Müllner - 3.19.92-1 +- Update to 3.19.92 + +* Thu Mar 03 2016 Florian Müllner - 3.19.91-1 +- Update to 3.19.91 + +* Fri Feb 19 2016 Florian Müllner - 3.19.90-1 +- Update to 3.19.90 + +* Wed Feb 03 2016 Fedora Release Engineering - 3.19.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jan 21 2016 Florian Müllner - 3.19.4-1 +- Update to 3.19.4 + +* Thu Dec 17 2015 Florian Müllner - 3.19.3-1 +- Update to 3.19.3 + +* Wed Nov 25 2015 Florian Müllner - 3.19.2-1 +- Update to 3.19.2 + +* Thu Oct 29 2015 Florian Müllner - 3.19.1-1 +- Update to 3.19.1 + +* Thu Oct 15 2015 Florian Müllner - 3.18.1-1 +- Update to 3.18.1 + +* Mon Sep 21 2015 Florian Müllner - 3.18.0-1 +- Update to 3.18.0 + +* Wed Sep 16 2015 Florian Müllner - 3.17.92-1 +- Update to 3.17.92 + +* Thu Sep 03 2015 Florian Müllner - 3.17.91-1 +- Update to 3.17.91 + +* Thu Aug 20 2015 Florian Müllner - 3.17.90-1 +- Update to 3.17.90 + +* Wed Aug 19 2015 Kalev Lember - 3.17.4-2 +- Don't own /usr/share/gnome-shell/extensions directory: now part of + gnome-shell package + +* Thu Jul 23 2015 Florian Müllner - 3.17.4-1 +- Update to 3.17.4 + +* Thu Jul 02 2015 Florian Müllner - 3.17.3-1 +- Update to 3.17.3 + +* Wed Jun 17 2015 Fedora Release Engineering - 3.17.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 27 2015 Florian Müllner - 3.17.2-1 +- Update to 3.17.2 + +* Fri May 01 2015 Kalev Lember - 3.17.1-2 +- Add glib-compile-schemas rpm scripts for screenshot-window-sizer + +* Thu Apr 30 2015 Florian Müllner - 3.17.1-1 +- Update to 3.17.1 + +* Tue Apr 14 2015 Florian Müllner - 3.16.1-1 +- Update to 3.16.1 + +* Mon Mar 23 2015 Florian Müllner - 3.16.0-1 +- Update to 3.16.0 + +* Tue Mar 17 2015 Florian Müllner - 3.15.92-1 +- Update to 3.15.92 + +* Thu Mar 05 2015 Kalev Lember - 3.15.91-2 +- Obsolete the systemMonitor extension that was dropped in 3.15.91 + +* Thu Mar 05 2015 Florian Müllner - 3.15.91-1 +- Update to 3.15.91 + +* Fri Feb 20 2015 Florian Müllner - 3.15.90-1 +- Update to 3.15.90 + +* Wed Jan 21 2015 Florian Müllner - 3.15.4-1 +- Update to 3.15.4 + +* Fri Dec 19 2014 Florian Müllner - 3.15.3.1-1 +- Update to 3.15.3.1 + +* Fri Dec 19 2014 Florian Müllner - 3.15.3-1 +- Update to 3.15.3 + +* Thu Nov 27 2014 Florian Müllner - 3.15.2-1 +- Update to 3.15.2 + +* Thu Oct 30 2014 Florian Müllner - 3.15.1-1 +- Update to 3.15.1 + +* Tue Oct 14 2014 Florian Müllner - 3.14.1-1 +- Update to 3.14.1 + +* Mon Sep 22 2014 Florian Müllner - 3.14.0-1 +- Update to 3.14.0 + +* Wed Sep 17 2014 Florian Müllner - 3.13.92-1 +- Update to 3.13.92 + +* Wed Sep 03 2014 Florian Müllner - 3.13.91-1 +- Update to 3.13.91 + +* Wed Aug 20 2014 Mohamed El Morabity - 3.13.90-1 +- Update to 3.13.90 + +* Thu Jul 24 2014 Kalev Lember - 3.13.4-1 +- Update to 3.13.4 + +* Thu Jun 26 2014 Richard Hughes - 3.13.3-1 +- Update to 3.13.3 + +* Sat Jun 07 2014 Fedora Release Engineering - 3.13.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Wed May 28 2014 Mohamed El Morabity - 3.13.2-1 +- Update to 3.13.2 + +* Fri May 02 2014 Kalev Lember - 3.13.1-1 +- Update to 3.13.1 + +* Tue Mar 25 2014 Richard Hughes - 3.12.0-1 +- Update to 3.12.0 + +* Thu Mar 20 2014 Mohamed El Morabity - 3.11.92-1 +- Update to 3.11.92 + +* Thu Mar 06 2014 Mohamed El Morabity - 3.11.91-1 +- Update to 3.11.91 + +* Thu Feb 20 2014 Mohamed El Morabity - 3.11.90-1 +- Update to 3.11.90 + +* Wed Feb 05 2014 Mohamed El Morabity - 3.11.5-1 +- Update to 3.11.5 + +* Mon Feb 03 2014 Mohamed El Morabity - 3.11.4-1 +- Update to 3.11.4 + +* Sun Dec 22 2013 Mohamed El Morabity - 3.11.3-1 +- Update to 3.11.3 + +* Wed Nov 13 2013 Mohamed El Morabity - 3.11.2-1 +- Update to 3.11.2 + +* Wed Oct 16 2013 Mohamed El Morabity - 3.10.1-1 +- Update to 3.10.1 + +* Tue Sep 24 2013 Mohamed El Morabity - 3.10.0-1 +- Update to 3.10.0 + +* Tue Sep 17 2013 Mohamed El Morabity - 3.9.92-1 +- Update to 3.9.92 + +* Tue Sep 03 2013 Mohamed El Morabity - 3.9.91-1 +- Update to 3.9.91 + +* Thu Aug 22 2013 Mohamed El Morabity - 3.9.90-1 +- Update to 3.9.90 +- Drop xrand-indicator subpackage, no longer provided upstream + +* Mon Aug 12 2013 Mohamed El Morabity - 3.9.5-3 +- Fix alternative-status-menu subpackage obsoleting + +* Mon Aug 12 2013 Nils Philippsen - 3.9.5-2 +- obsolete alternative-status-menu subpackage to allow smooth upgrades + +* Sun Aug 04 2013 Mohamed El Morabity - 3.9.5-1 +- Update to 3.9.5 +- Drop alternative-status-menu subpackage, no longer provided upstream + +* Sat Aug 03 2013 Fedora Release Engineering - 3.9.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Thu Jun 20 2013 Rahul Sundaram - 3.9.3-1 +- Update to 3.9.3 +- Obsolete default-min-max and static workspaces extensions +- Use make_install macro +- Fix bogus dates in spec changelog + +* Tue May 28 2013 Mohamed El Morabity - 3.9.2-1 +- Update to 3.9.2 + +* Fri May 10 2013 Mohamed El Morabity - 3.9.1-1 +- Update to 3.9.1 + +* Fri May 10 2013 Kalev Lember - 3.8.1-3 +- Obsolete gnome-applet-sensors + +* Wed May 01 2013 Kalev Lember - 3.8.1-2 +- Obsolete a few more fallback mode packages +- Remove gnome-panel provides + +* Tue Apr 16 2013 Matthias Clasen - 3.8.1-1 +- Update to 3.8.1 + +* Tue Mar 26 2013 Mohamed El Morabity - 3.8.0-1 +- Update to 3.8.0 + +* Tue Mar 19 2013 Ray Strode 3.7.92-1 +- Update to 3.7.92 + +* Tue Mar 05 2013 Mohamed El Morabity - 3.7.91-1 +- Update to 3.7.91 + +* Sat Mar 02 2013 Adel Gadllah - 3.7.90-2 +- Obsolete gnome-panel + +* Fri Feb 22 2013 Kalev Lember - 3.7.90-1 +- Update to 3.7.90 + +* Thu Feb 07 2013 Kalev Lember - 3.7.5.1-2 +- Depend on gnome-shell 3.7.5, there's no 3.7.5.1 + +* Thu Feb 07 2013 Mohamed El Morabity - 3.7.5.1-1 +- Update to 3.7.5 +- Enable new launch-new-instance and window-list extensions, and add them in the + classic-mode extension set +- Re-add places-menu in the classic-mode extension set + +* Wed Jan 16 2013 Mohamed El Morabity - 3.7.4-1 +- Update to 3.7.4 +- places-menu extension no longer part of the classic-mode extension set + +* Tue Jan 01 2013 Mohamed El Morabity - 3.7.3-1 +- Update to 3.7.3 +- Enable new default-min-max and static-workspaces extensions +- Provide new subpackage gnome-classic-session +- Revamp summaries and descriptions + +* Tue Oct 30 2012 Mohamed El Morabity - 3.7.1-1 +- Update to 3.7.1 +- Drop dock and gajim extensions, no longer provided + +* Tue Oct 30 2012 Mohamed El Morabity - 3.6.1-1 +- Update to 3.6.1 + +* Tue Oct 02 2012 Mohamed El Morabity - 3.6.0-1 +- Update to 3.6.0 + +* Thu Sep 06 2012 Mohamed El Morabity - 3.5.91-1 +- Update to 3.5.91 + +* Wed Aug 29 2012 Mohamed El Morabity - 3.5.90-1 +- Update to 3.5.90 + +* Sat Aug 11 2012 Mohamed El Morabity - 3.5.5-1 +- Update to 3.5.5 + +* Sun Jul 22 2012 Mohamed El Morabity - 3.5.4-1 +- Update to 3.5.4 + +* Wed Jul 18 2012 Mohamed El Morabity - 3.5.2-1 +- Update to 3.5.2 +- Drop useless Provides/Obsoletes + +* Sat Mar 24 2012 Mohamed El Morabity - 3.4.0-1 +- Update to 3.4.0 +- Minor spec fixes + +* Sat Mar 24 2012 Mohamed El Morabity - 3.3.92-1 +- Update to 3.3.92 + +* Tue Feb 28 2012 Mohamed El Morabity - 3.3.90-1 +- Update to 3.3.90 + +* Thu Feb 16 2012 Mohamed El Morabity - 3.3.5-1 +- Update to 3.3.5 +- Spec cleanup + +* Fri Jan 13 2012 Fedora Release Engineering - 3.3.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Nov 30 2011 Mohamed El Morabity - 3.3.2-1 +- Update to 3.3.2 + +* Wed Nov 30 2011 Mohamed El Morabity - 3.2.1-1 +- Update to 3.2.1 +- Fix alternative-status-menu extension crash when login + +* Wed Nov 09 2011 Mohamed El Morabity - 3.2.0-2 +- Fix dock and alternate-tab extensions +- Fix GNOME Shell version to work with GS 3.2.1 + +* Mon Oct 03 2011 Mohamed El Morabity - 3.2.0-1 +- Update to 3.2.0 + +* Mon Sep 26 2011 Mohamed El Morabity - 3.1.91-3.20111001gite102c0c6 +- Update to a newer git snapshot +- Fix GNOME Shell version to work with GS 3.2.0 +- Add Requires on GS 3.2.0 or above to gnome-shell-common + +* Wed Sep 14 2011 Mohamed El Morabity - 3.1.91-2 +- Enable xrandr-indicator and workspace-indicator extensions + +* Mon Sep 12 2011 Michel Salim - 3.1.91-1 +- Update to 3.1.91 +- add more documentation + +* Thu Sep 1 2011 Michel Salim - 3.1.4-3.20110830git6b5e3a3e +- Update to git snapshot, for gnome-shell 3.1.90 + +* Sun Aug 21 2011 Michel Salim - 3.1.4-2 +- Enable apps-menu extension +- Spec cleanup + +* Sun Aug 21 2011 Michel Salim - 3.1.4-1 +- Update to 3.1.4 +- Enable systemMonitor extension +- Prepare xrandr-indicator, commenting out since it does not seem to work yet +- Rename subpackages in line with new guidelines (# 715367) +- Sort subpackages in alphabetical order + +* Sat May 28 2011 Timur Kristóf - 3.0.2-1.g63dd27cgit +- Update to a newer git snapshot +- Fix RHBZ bug #708230 +- Enabled systemMonitor extension, but commented out since the requirements are not available + +* Fri May 13 2011 Mohamed El Morabity - 3.0.1-3.03660fgit +- Update to a newer git snapshot +- Enable native-window-placement extension + +* Fri May 06 2011 Rahul Sundaram - 3.0.1-2b20cbagit +- Fix description + +* Thu May 5 2011 Elad Alfassa - 3.0.1-1.b20cbagit +- Update to a newer git snapshot +- Enabled the places-menu extension + +* Tue Apr 26 2011 Mohamed El Morabity - 3.0.1-1.f016b9git +- Update to a newer git snapshot (post-3.0.1 release) +- Enable drive-menu extension + +* Mon Apr 11 2011 Mohamed El Morabity - 3.0.0-5.6d56cfgit +- Enable auto-move-windows extension + +* Mon Apr 11 2011 Rahul Sundaram - 3.0.0-4.6d56cfgit +- Add glib2-devel as build requires + +* Mon Apr 11 2011 Rahul Sundaram - 3.0.0-3.6d56cfgit +- Tweak description +- Fix typo in configure + +* Mon Apr 11 2011 Rahul Sundaram - 3.0.0-2.6d56cfgit +- Added the user-theme extension +- Patch from Timur Kristóf + +* Fri Apr 08 2011 Rahul Sundaram - 3.0.0-1.6d56cfgit +- Make sure configure doesn't get called twice + +* Fri Apr 08 2011 Rahul Sundaram - 3.0.0-0.6d56cfgit +- Initial build