Compare commits

..

28 Commits

Author SHA1 Message Date
Florian Müllner
e5ff28e45d Bump version to 46.3
Update NEWS.
2025-01-12 22:06:57 +01:00
Bartłomiej Piotrowski
a1ce38fee8 ci: Switch to GNOME GitLab mirror of ci-templates
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/368>
(cherry picked from commit 0f69d7663b)
2025-01-10 14:09:42 +01:00
Florian Müllner
ce302b0dfd ci: Adapt to updated release module template
The release module moved into production now. The process changed
slightly with regard to the testing period, so we will have to
adapt the existing job a bit.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/367>
(cherry picked from commit 5d8d3601b4)
2025-01-10 14:08:08 +01:00
Florian Müllner
a168041b82 ci: Move LINT_LOG variable out of global section
It is only used by the eslint job, so better define it there.

While at it, make sure the variable is quoted as that's considered
good practice (even when safe to use unquoted as in this case).

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/367>
(cherry picked from commit ea77b557e5)
2025-01-10 14:07:01 +01:00
Florian Müllner
c735818868 ci: Use variable for meson build directory
This ensures that the value is consistent between jobs.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/367>
(cherry picked from commit 9f48149346)
2025-01-10 14:06:52 +01:00
Florian Müllner
106ae2c28d Revert "ci: Use meson introspect to generate artifact path"
The new release service that now moved into production expects
the tag to match the release version.

Instead of using the $VERSION-real pattern in case of error,
switch to a pre-push hook to hopefully prevent those errors
in the first place:

  https://gitlab.gnome.org/-/snippets/6710

This reverts commit 8c014a6b1d.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/367>
(cherry picked from commit 0d1b279a64)
2025-01-10 14:06:44 +01:00
Florian Müllner
363f396365 workspace-indicator: Do not only exclude DESKTOP windows
There are other window types that should be excluded from workspace
previews, including more common ones like menus. Instead of checking
for a variety of window types, delegate the decision to mutter by
checking for the `skip-taskbar` property.

(The internal `skip-pager` property would be more apt in this case,
but as it only differs from `skip-taskbar` for X11 clients that
explicitly set one and not the other, it shouldn't matter in practice)

Closes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/537
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/363>
(cherry picked from commit 77a11fd9cd)
2025-01-10 14:06:34 +01:00
Florian Müllner
62ccff1558 window-list: Untrack chrome while in overview
The window list is set up to track the monitor's fullscreen state.
Monitors are never considered in fullscreen while showing the overview,
so if shell's layout manager updates the fullscreen visibility after
we hid the bottom bar, it ends up being visible in the overview.

To avoid this, untrack the actor while the overview is visible.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/509
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/364>
(cherry picked from commit 981e8e42e2)
2025-01-10 14:06:25 +01:00
Florian Müllner
959dc522e7 window-list: Fix disconnecting window signals in context menu
Menus are not actors themselves, so they are not "destroyables" in
terms of automatic signal disconnection, with the result that we
currently leak window signals.

Fix this by using the menu's actor as tracked object, so the signals
are disconnected automatically when the actor is destroyed.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/474
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/362>
(cherry picked from commit 4a841dfd49)
2025-01-10 14:06:14 +01:00
Florian Müllner
a75f8a7d52 places-menu: Update fake mount operation source
gnome-shell now checks for an associated drive to automatically
cancel the operation on disconnect, so fake the corresponding
method. While at it, drop the `get_icon()` method that hasn't
been used for quite a while now.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/508
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/361>
(cherry picked from commit 8957f488dc)
2025-01-10 14:05:58 +01:00
Florian Müllner
f3144d472a places-menu: Catch errors during async operation
Uncaught errors in async functions don't provide a good stack, because
the unhandled promise rejection masks the error that triggered it.

While we already handle *expected* errors inside the function, make
sure we catch all errors to get useful stack information for unexpected
errors as well.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/361>
(cherry picked from commit e0b68a319e)
2025-01-10 14:05:46 +01:00
Florian Müllner
566e7806b0 places-menu: Inherit from PopupImageMenuItem
PopupImageMenuItems used to position the icon after the label,
so we ended up with our own icon+label items.

However the icon position was changed years ago in the shell, so
inherit from PopupImageMenuItem instead.

This does not only simplify the code a bit, but also pulls in
features we are currently missing, like a11y labelling.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/542
(cherry picked from commit 568826e489)
2025-01-10 14:05:25 +01:00
Florian Müllner
d3cf3c0961 build: Sync check-version script with gnome-shell
The script was updated to not require appstream-util to check for
a corresponding release element in metainfo.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/354>
(cherry picked from commit 1218aee87f)
2025-01-10 14:05:06 +01:00
Florian Müllner
084a2ed7c7 cleanup: Use consistent line break style in meson.build
Either have all arguments on the same line, or have a separate
line for every argument (that is, don't special-case the first
arg).

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit 265935e14b)
2025-01-10 14:04:51 +01:00
Florian Müllner
b8f7287205 cleanup: Fix indent errors in meson.build
We are supposed to use a 2-space indent, but some inconsistencies
sneaked in over time.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit b903618050)
2025-01-10 13:59:59 +01:00
Florian Müllner
965cad8b95 cleanup: Always use dangling commas in meson.build
This is meson's default formatting, and matches what we already
do in JS.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit 720933b08e)
2025-01-10 13:59:49 +01:00
Florian Müllner
b7f737492d cleanup: Use format strings in meson.build
Those are a bit more concise than ''.format(), and have been
in meson for a long time.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit 85ee8829bf)
2025-01-10 13:58:21 +01:00
Florian Müllner
6b34c996d3 build: Use SPDX identifier for license
Meson strongly recommends to use SPDX identifiers for the license
string, and there's no reason for us to not do so.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit 6df4905286)
2025-01-10 13:58:17 +01:00
Florian Müllner
7f23ccbff7 places-menu: Remove left-over modeline
This one slipped through commit 253ddb864 ...

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/370>
(cherry picked from commit 83c41bad30)
2025-01-10 13:57:20 +01:00
Florian Müllner
c06c33b488 extensions: Remove modelines
We already include an .editorconfig that is supported by many
editors, including emacs, so no need to repeat an emacs-specific
modeline in every source file.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit 253ddb8642)
2025-01-10 13:39:42 +01:00
Florian Müllner
043a268b57 Add .editorconfig
This should ensure that all editors which support
https://editorconfig.org/ use the correct indentation
with spaces (not tabs) by default.

This is hardly a full specification of our coding style,
but it's a correct subset and better than nothing.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/353>
(cherry picked from commit 0ca156a2b6)
2025-01-10 13:37:43 +01:00
Florian Müllner
f44f90b966 export-zips: Use --destdir instead of custom prefix
meson skips some steps like schema compilation when DESTDIR is
set, so this is slightly more efficient.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/345>
(cherry picked from commit 8f75ccae34)
2025-01-10 13:35:36 +01:00
twlvnn kraftwerk
a99515feef Update Bulgarian translation 2024-09-02 08:47:19 +00:00
Giannis Antypas
7953cd130d Update Greek translation 2024-08-12 20:30:42 +00:00
Daniel Șerbănescu
75b1ea879b Update Romanian translation 2024-08-05 20:05:43 +00:00
Chao-Hsiung Liao
b89a93a4fc Update Chinese (Taiwan) translation 2024-07-24 10:26:12 +00:00
Jose Riha
a00a7d7a9a Update Slovak translation 2024-07-05 20:01:58 +00:00
Милош Поповић
3bbbb5dac7 Update Serbian translation 2024-06-20 14:59:31 +00:00
143 changed files with 5780 additions and 10077 deletions

7
.eslintrc.yml Normal file
View File

@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2019 Florian Müllner <fmuellner@gnome.org>
#
# SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
extends:
- ./lint/eslintrc-gjs.yml
- ./lint/eslintrc-shell.yml

4
.gitattributes vendored
View File

@@ -1,4 +0,0 @@
# SPDX-FileCopyrightText: No rights reserved
# SPDX-License-Identifier: CC0-1.0
package-lock.json -diff

2
.gitignore vendored
View File

@@ -9,6 +9,4 @@ zip-files/
*.patch
*.sw?
.buildconfig
.eslintcache
.vscode
node_modules

View File

@@ -3,12 +3,8 @@
# SPDX-License-Identifier: GPL-2.0-or-later
include:
- project: Infrastructure/freedesktop-ci-templates
file: templates/fedora.yml
- project: Infrastructure/freedesktop-ci-templates
file: templates/ci-fairy.yml
- project: GNOME/citemplates
file: templates/default-rules.yml
- remote: 'https://gitlab.gnome.org/Infrastructure/freedesktop-ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/fedora.yml'
- remote: "https://gitlab.gnome.org/Infrastructure/freedesktop-ci-templates/-/raw/6f86b8bcb0cd5168c32779c4fea9a893c4a0c046/templates/ci-fairy.yml"
- component: gitlab.gnome.org/GNOME/citemplates/release-service@master
inputs:
job-stage: deploy
@@ -16,21 +12,39 @@ include:
tarball-artifact-path: "$TARBALL_ARTIFACT_PATH"
stages:
- pre-review
- pre_review
- prepare
- review
- build
- deploy
default:
image: registry.gitlab.gnome.org/gnome/gnome-shell/fedora/43:2025-09-10.1
image: registry.gitlab.gnome.org/gnome/gnome-shell/fedora/40:2024-02-23.0
# Cancel jobs if newer commits are pushed to the branch
interruptible: true
# Auto-retry jobs in case of infra failures
retry:
max: 1
when:
- 'runner_system_failure'
- 'stuck_or_timeout_failure'
- 'scheduler_failure'
- 'api_failure'
variables:
FDO_UPSTREAM_REPO: GNOME/gnome-shell-extensions
MESON_BUILD_DIR: build
TARBALL_ARTIFACT_PATH: "${MESON_BUILD_DIR}/meson-dist/${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.xz"
.pipeline-guard:
workflow:
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
when: never
- if: '$CI_MERGE_REQUEST_IID'
- if: '$CI_COMMIT_TAG'
- if: '$CI_COMMIT_BRANCH'
.pipeline_guard: &pipeline_guard
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_TAG'
@@ -38,14 +52,15 @@ variables:
- if: '$CI_COMMIT_BRANCH =~ /^gnome-[0-9-]+$/'
- when: 'manual'
.prereview-req:
.prereview_req: &prereview_req
needs:
- check-commit-log
- check_commit_log
- check-merge-request
check-commit-log:
check_commit_log:
extends:
- .fdo.ci-fairy
stage: pre-review
stage: pre_review
script:
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
then
@@ -53,8 +68,7 @@ check-commit-log:
else
echo "Not a merge request" ;
fi
rules:
- !reference [.pipeline-guard, rules]
<<: *pipeline_guard
artifacts:
expire_in: 1 week
paths:
@@ -62,37 +76,56 @@ check-commit-log:
reports:
junit: commit-message-junit-report.xml
check-merge-request:
extends:
- .fdo.ci-fairy
stage: pre_review
script:
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
then
ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request-report.xml ;
else
echo "Not a merge request" ;
fi
<<: *pipeline_guard
artifacts:
expire_in: 1 week
paths:
- check-merge-request-report.xml
reports:
junit: check-merge-request-report.xml
check-reuse:
stage: pre-review
stage: pre_review
image:
name: fsfe/reuse:latest
entrypoint: [""]
script:
- reuse lint
js-check:
js_check:
stage: review
needs:
- !reference [.prereview-req, needs]
<<: *prereview_req
script:
- gjs-check-syntax
eslint:
stage: review
needs:
- !reference [.prereview-req, needs]
<<: *prereview_req
variables:
LINT_LOG: "eslint-report.xml"
script:
- ./tools/run-eslint.sh --output-file "$LINT_LOG" --format junit --stdout
- export NODE_PATH=$(npm root -g)
- ./.gitlab-ci/run-eslint --output-file "$LINT_LOG" --format junit --stdout
artifacts:
paths:
- "$LINT_LOG"
reports:
junit: "$LINT_LOG"
potfile-js-check:
potfile_js_check:
stage: review
needs:
- !reference [.prereview-req, needs]
<<: *prereview_req
script:
- gjs-check-potfiles
artifacts:
@@ -101,8 +134,7 @@ potfile-js-check:
build-bundles:
stage: build
needs:
- !reference [.prereview-req, needs]
<<: *prereview_req
script:
- ./export-zips.sh
artifacts:
@@ -111,19 +143,9 @@ build-bundles:
paths:
- zip-files/
dist-bundles:
stage: deploy
needs:
- build-bundles
script:
- gnome-extensions upload --accept-tos --user "$EGO_USER" --password "$EGO_PASSWORD" zip-files/*.zip
rules:
- if: '$CI_COMMIT_TAG'
fedora-build:
stage: build
needs:
- !reference [.prereview-req, needs]
<<: *prereview_req
script:
- meson setup "$MESON_BUILD_DIR" --werror -Dextension_set=all -Dclassic_mode=true
- meson compile -C "$MESON_BUILD_DIR"

58
.gitlab-ci/run-eslint Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env node
// SPDX-FileCopyrightText: 2023 Florian Müllner <fmuellner@gnome.org>
//
// SPDX-License-Identifier: GPL-2.0-or-later
const {ESLint} = require('eslint');
console.log(`Running ESLint version ${ESLint.version}...`);
const fs = require('fs');
const path = require('path');
function hasOption(...names) {
return process.argv.some(arg => names.includes(arg));
}
function getOption(...names) {
const optIndex =
process.argv.findIndex(arg => names.includes(arg)) + 1;
if (optIndex === 0)
return undefined;
return process.argv[optIndex];
}
(async function main() {
const outputOption = getOption('--output-file', '-o');
const outputPath = outputOption ? path.resolve(outputOption) : null;
const sourceDir = path.dirname(process.argv[1]);
process.chdir(path.resolve(sourceDir, '..'));
const sources = ['extensions'];
const eslint = new ESLint();
const results = await eslint.lintFiles(sources);
const formatter = await eslint.loadFormatter(getOption('--format', '-f'));
const resultText = formatter.format(results);
if (outputPath) {
fs.mkdirSync(path.dirname(outputPath), {recursive: true});
fs.writeFileSync(outputPath, resultText);
if (hasOption('--stdout')) {
const consoleFormatter = await eslint.loadFormatter();
console.log(consoleFormatter.format(results));
}
} else {
console.log(resultText);
}
process.exitCode = results.some(r => r.errorCount > 0) ? 1 : 0;
})().catch((error) => {
process.exitCode = 1;
console.error(error);
});

View File

@@ -1,72 +0,0 @@
<!--
Please read https://handbook.gnome.org/issues/reporting.html
first to ensure that you create a clear and specific issue.
-->
### Which extension
<!--
Which extension is the issue about?
See the project README for a complete list of extensions:
https://gitlab.gnome.org/GNOME/gnome-shell-extensions#extensions
Do not report issues for any other extensions here.
Report general issues about gnome-shell's extension support to
https://gitlab.gnome.org/GNOME/gnome-shell.
Report issues with the extensions.gnome.org website to
https://gitlab.gnome.org/Infrastructure/extensions-web/
-->
### Affected version
<!--
Provide at least the following information:
* Your OS and version
* Extension version
* Affected GNOME Shell version
-->
### Bug summary
<!--
Provide a short summary of the bug you encountered.
-->
### Steps to reproduce
<!--
1. Step one
2. Step two
3. ...
-->
### What happened
<!--
What did the extension do that was unexpected?
-->
### What did you expect to happen
<!--
What did you expect the extension to do?
-->
### Relevant logs, screenshots, screencasts etc.
<!--
If you have further information, such as technical documentation, logs,
screenshots or screencasts related, please provide them here.
If the bug is a crash, please obtain a stack trace with installed debug
symbols (at least for GNOME Shell and Mutter) and attach it to
this issue following the instructions on
https://handbook.gnome.org/issues/stack-traces.html.
-->
<!-- Do not remove the following line. -->
/label ~"1. Bug"

View File

@@ -1,2 +0,0 @@
SPDX-FileCopyrightText: 2024 Florian Müllner <fmuellner@gnome.org>
SPDX-License-Identifier: CC-BY-SA-4.0

View File

@@ -1,47 +0,0 @@
<!--
Please read https://handbook.gnome.org/issues/reporting.html
first to ensure that you create a clear and specific issue.
-->
### Which extension
<!--
Which extension is the issue about?
See the project README for a complete list of extensions:
https://gitlab.gnome.org/GNOME/gnome-shell-extensions#extensions
Do not report issues for any other extensions here.
Report general issues about gnome-shell's extension support to
https://gitlab.gnome.org/GNOME/gnome-shell.
Report issues with the extensions.gnome.org website to
https://gitlab.gnome.org/Infrastructure/extensions-web/
-->
### Feature summary
<!--
Describe what you would like to be able to do with the extension
that you currently cannot do.
-->
### How would you like it to work
<!--
If you can think of a way the extension might be able to do this,
let us know here.
-->
### Relevant links, screenshots, screencasts etc.
<!--
If you have further information, such as technical documentation,
code, mockups or a similar feature in another desktop environments,
please provide them here.
-->
<!-- Do not remove the following line. -->
/label ~"1. Feature"

View File

@@ -1,3 +0,0 @@
SPDX-FileCopyrightText: 2024 Florian Müllner <fmuellner@gnome.org>
SPDX-License-Identifier: CC-BY-SA-4.0

22
.reuse/dep5 Normal file
View File

@@ -0,0 +1,22 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: gnome-shell-extensions
Upstream-Contact: Florian Müllner <fmuellner@gnome.org>
Source: https://gitlab.gnome.org/GNOME/gnome-shell-extensions
Files: NEWS README.md HACKING.md data/HACKING
Copyright: No rights reserved
License: CC0-1.0
Files: *.json.in *.desktop.in *.gschema.override
Copyright: Florian Müllner <fmuellner@gnome.org>
License: GPL-2.0-or-later
# managed by translation teams
Files: po/*.po
Copyright: GNOME Translation Teams <i18n@gnome.org>
License: GPL-2.0-or-later
# managed by translation teams
Files: po/LINGUAS po/POTFILES.in
Copyright: No rights reserved
License: CC0-1.0

View File

@@ -1,9 +1,3 @@
<!--
SPDX-FileCopyrightText: 2011 Giovanni Campagna <gcampagna@src.gnome.org>
SPDX-FileCopyrightText: 2017 Florian Müllner <fmuellner@gnome.org>"""
SPDX-License-Identifier: CC-BY-SA-4.0
-->
## Creating a New Extension
To create a new extension, add a subdirectory in extensions. Then create

View File

@@ -1,170 +0,0 @@
Creative Commons Attribution-ShareAlike 4.0 International
Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is” basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors.
Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensors permission is not necessary for any reasonfor example, because of any applicable exception or limitation to copyrightthen that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public.
Creative Commons Attribution-ShareAlike 4.0 International Public License
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
Section 1 Definitions.
a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses, approved by Creative Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
e. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
i. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights under this Public License.
k. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
Section 2 Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
A. reproduce and Share the Licensed Material, in whole or in part; and
B. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
3. Term. The term of this Public License is specified in Section 6(a).
4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
5. Downstream recipients.
A. Offer from the Licensor Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
B. Additional offer from the Licensor Adapted Material. Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapters License You apply.
C. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this Public License.
3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
Section 3 License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified form), You must:
A. retain the following if it is supplied by the Licensor with the Licensed Material:
i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of warranties;
v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
b. ShareAlike.In addition to the conditions in Section 3(a), if You Share Adapted Material You produce, the following conditions also apply.
1. The Adapters License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply.
Section 4 Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
Section 5 Disclaimer of Warranties and Limitation of Liability.
a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
Section 6 Term and Termination.
a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
2. upon express reinstatement by the Licensor.
c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
Section 7 Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
Section 8 Interpretation.
a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
Creative Commons may be contacted at creativecommons.org.

178
NEWS
View File

@@ -1,189 +1,31 @@
50.alpha
========
* classic: Drop xorg sessions [Jordan; !283]
* classic: Deifne a gnome-session session [Adrian; !3960]
* Misc. bug fixes and cleanups [Florian, Jordan; !425, !429, !430, !432, !431,
!433, !434, !435, !439]
Contributors:
Florian Müllner, Jordan Petridis, Adrian Vovk
Translators:
BoF ButterflyOfFire [kab], Giannis Antypas [el],
Asier Saratsua Garmendia [eu], Hugo Carvalho [pt], twlvnn kraftwerk [bg],
Baurzhan Muftakhidinov [kk], Ibai Oihanguren Sala [eu]
49.0
46.3
====
* window-list: Adjust to gnome-shell changes [Florian; !421]
* system-monitor: Unbreak on BSD [Antoine; !356]
* Misc. bug fixes and cleanups [Florian; !422, !423]
Contributors:
Antoine Jacoutot, Florian Müllner
Translators:
Jiri Grönroos [fi], Aurimas Aurimas Černius [lt]
49.rc
=====
Translators:
Emilio Sepúlveda [ia], Dušan Kazik [sk], Daniel Rusek [cs],
Nathan Follens [nl], Piotr Drąg [pl], Balázs Úr [hu], Yosef Or Boczko [he]
49.beta
=======
* Misc. bug fixes and cleanups [Florian; !408]
Contributors:
Florian Müllner
Translators:
Anders Jonsson [sv], Makoto Sakaguchi [ja], Danial Behzadi [fa],
Jordi Mas i Hernandez [ca]
49.alpha.1
==========
* workspaces-indicator, window-list: Better expose workspace names
[Florian; !405]
* window-list: Animate transition to/from overview [Florian; !412]
* Misc. bug fixes and cleanups [Florian; !409, !411, !413]
Contributors:
Florian Müllner
Translators:
Martin [sl], Emin Tufan Çetin [tr], Yuri Chornoivan [uk], Luming Zh [zh_CN],
Yago Raña [gl], Ekaterine Papava [ka], Vasil Pupkin [be],
Álvaro Burns [pt_BR], Sergej A. [ru]
49.alpha.0
==========
* windowsNavigator: Fix handling keyboard shortcuts [Daniel; !395]
* build: Allow disabling the X11 session [Neal; !396, !400]
* Disable X11 session by default [Jordan; !399]
* Misc. bug fixes and cleanups [Florian; !398, !406]
Contributors:
Daniel Buch Hansen, Neal Gompa, Florian Müllner, Jordan Petridis
Translators:
Emilio Sepúlveda [ia]
48.1
====
Translators:
Hugo Carvalho [pt], Danial Behzadi [fa]
48.0
====
* apps-menu: Fix scrolling items into view on keynav [Victor; !391]
* Misc. bug fixes and cleanups [Florian, Stuart; !390, !392]
Contributors:
Stuart Hayhurst, Victor Kareh, Florian Müllner
48.rc
=====
* Misc. bug fixes and cleanups [Florian; !385, !388]
Contributors:
Florian Müllner
Translators:
Emilio Sepúlveda [ia], Mathews M [ml], Daniel Rusek [cs], Piotr Drąg [pl],
Anders Jonsson [sv], Ekaterine Papava [ka], Yuri Chornoivan [uk],
Aurimas Černius [lt], Luming Zh [zh_CN], Jiri Grönroos [fi]
48.beta
=======
* window-list: Fix regression in chrome tracking [Florian; !379]
* Misc. bug fixes and cleanups [Florian; !380]
Contributors:
Florian Müllner, Emilio Sepúlveda
Translators:
Rafael Fontenelle [pt_BR], Emilio Sepúlveda [ia]
48.alpha
========
* classic: Add missing top-bar indicators [Florian; !339]
* window-list: Fix window state styling [Florian; !342]
* window-list: Fix "ignore-workspace" setting getting reset [Florian; !341]
* window-list: Allow rearranging window buttons [Florian, Jakub; !338]
* window-list: Add workspaces page to preference dialog [Florian; !344]
* places-menu: Sync list of places with nautilus [Florian; !340]
* places-menu: Fix a11y labelling [Florian; #542]
* places-menu: Fix opening drives with mount operations [Florian; !361]
* window-list: Fix hiding when entering overview with gestures [Florian; !364]
* workspace-indicator: Only show previews of regular windows [Florian; !363]
* window-list: Add attention indicator [Florian; !366]
* Misc. bug fixes and cleanups [Florian, Bartłomiej; !337, !343, !345, !347,
!348, !349, !351, !352, !353, !354, !358, !362, !365, !367, !368, !370, !375]
* Misc. bug fixes and cleanups [Florian, Bartłomiej; !345, !353, !370, !354,
!362, !367, !368]
Contributors:
Florian Müllner, Bartłomiej Piotrowski, Jakub Steiner
Florian Müllner, Bartłomiej Piotrowski
Translators:
Fabio Tomat [fur], Martin [sl], Jordi Mas i Hernandez [ca], Vasil Pupkin [be],
Nathan Follens [nl], Artur S0 [ru], Марко Костић [sr],
Yaron Shahrabani [he], Sabri Ünal [tr], Yi-Jyun Pan [zh_TW]
Милош Поповић [sr], Jose Riha [sk], Chao-Hsiung Liao [zh_TW],
Daniel Șerbănescu [ro], Giannis Antypas [el], twlvnn kraftwerk [bg]
47.0
46.2
====
Translators:
twlvnn kraftwerk [bg], Alexander Shopov [bg], Fran Dieguez [gl],
Aurimas Černius [lt], Daniel [es], Andika Triwidada [id],
Andi Chandler [en_GB], Ask Hjorth Larsen [da], Aefgh Threenine [th],
Dušan Kazik [sk], Rūdolfs Mazurs [lv], Irénée THIRION [fr]
47.rc
=====
* Misc. bug fixes and cleanups [Sophie; !333]
Contributors:
Sophie Herold
Translators:
Daniel Șerbănescu [ro], Giannis Antypas [el], Ekaterine Papava [ka],
Jordi Mas i Hernandez [ca], Yuri Chornoivan [uk], Jiri Grönroos [fi],
Daniel Rusek [cs], Vasil Pupkin [be], Luming Zh [zh_CN], Brage Fuglseth [nb],
Asier Sarasua Garmendia [eu], Danial Behzadi [fa], Rafael Fontenelle [pt_BR],
Quentin PAGÈS [oc], Anders Jonsson [sv], Jürgen Benvenuti [de],
Changwoo Ryu [ko], Hugo Carvalho [pt], Piotr Drąg [pl], Sabri Ünal [tr]
47.beta
=======
* window-list: Modernize styling [Jakub; !330]
* Include "status-icons" extension [Florian; !194]
* Misc. bug fixes and cleanups [Florian; !328, !331, !327]
Contributors:
Florian Müllner, Jakub Steiner
Translators:
Sabri Ünal [tr], Chao-Hsiung Liao [zh_TW]
47.alpha
========
* Improve workspace previews in window-list and workspace-indicator
[Florian; !307, !316]
* apps-menu: Fix a11y of category labels [Florian; !319]
* window-list: Fix long-press support [Florian; !320]
* window-list: Animate transitions [Florian; !325]
* Misc. bug fixes and cleanups [Florian; !315, !321, !324]
* Misc. bug fixes and cleanups [Florian; !324]
Contributors:
Florian Müllner
Translators:
Jordi Mas i Hernandez [ca], Martin [sl], Hugo Carvalho [pt], Jose Riha [sk],
Scrambled 777 [hi], Artur S0 [ru], Милош Поповић [sr], Yosef Or Boczko [he],
Balázs Úr [hu]
Hugo Carvalho [pt], Jose Riha [sk], Jordi Mas i Hernandez [ca],
Scrambled 777 [hi]
46.1
====

108
README.md
View File

@@ -1,34 +1,25 @@
<!--
SPDX-FileCopyrightText: 2011 Giovanni Campagna <gcampagna@src.gnome.org>
SPDX-FileCopyrightText: 2011 Adam Dingle <adam@yorba.org>
SPDX-FileCopyrightText: 2011 Vamsi Krishna Brahmajosyula <vamsikrishna.brahmajosyula@gmail.com>
SPDX-FileCopyrightText: 2014 Michael Catanzaro <mcatanzaro@gnome.org>
SPDX-FileCopyrightText: 2015 Florian Müllner <fmuellner@gnome.org>
SPDX-FileCopyrightText: 2019 Fabian P. Schmidt <kerel-fs@gmx.de>
SPDX-FileCopyrightText: 2024 Aral Balkan <aral@aralbalkan.com>"""
SPDX-License-Identifier: CC-BY-SA-4.0
-->
# GNOME Shell Extensions
GNOME Shell Extensions is a collection of extensions providing additional
and optional functionality to GNOME Shell.
The extensions in this package are supported by GNOME and will be updated
to reflect future API changes in GNOME Shell.
Since GNOME Shell is not API stable, extensions work only against a very
specific version of the shell, usually the same as this package (see
"configure --version"). The extensions in this package are supported by GNOME
and will be updated to reflect future API changes in GNOME Shell.
Both the most recent stable release and the previous stable release of
GNOME Shell are actively supported, as well as the current development
branch.
The GNOME wiki has more information about [GNOME Shell Extensions][project-page],
as well as some general information about [GNOME Shell][shell-page].
Please refer to the [schedule] to see when a new version will be released.
[schedule]: https://release.gnome.org/calendar
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
## Extensions
The following is a complete list of extensions that are provided by this
project.
* alternate-tab (**OBSOLETE**)
Lets you use classic Alt+Tab (window-based instead of app-based) in GNOME Shell.
This extension is obsolete since GNOME 3.30, see [this blogpost][alternatetab-post]
for further details.
* apps-menu
@@ -37,7 +28,8 @@ project.
* auto-move-windows
Lets you manage your workspaces more easily, assigning a specific workspace to
each application as soon as it creates a window.
each application as soon as it creates a window, in a manner configurable with a
GSettings key.
* drive-menu
@@ -48,11 +40,6 @@ project.
Changes application icons to always launch a new instance when activated.
* light-style
Changes the default shell style to "light", while still following the
system-wide "dark" preference.
* native-window-placement
An alternative algorithm for layouting the thumbnails in the windows overview, that
@@ -66,17 +53,9 @@ project.
Adds a shortcut for resizing the focus window to a size that is suitable for GNOME Software screenshots. Ctrl + Alt + s cycles forwards through the available sizes and Ctrl + Alt + Shift + s cycles backwards.
* status-icons
Show (XEmbed) status icons in the top bar.
* system-monitor
Shows system usage information in the top bar.
* user-theme
Loads a shell theme from `$XDG_DATA_HOME/themes/<name>/gnome-shell`.
Loads a shell theme from ~/.themes/<name>/gnome-shell.
* window-list
@@ -90,49 +69,18 @@ project.
Adds a simple workspace switcher to the top bar.
### Ex-Extensions
## Default branch
Occasionally over the years, some extensions were removed.
The following list is not complete, but limited to cases that
are notable for some reason; either the removal happened
relatively recently, or the extension used to be particularly
popular in the past.
* alternate-tab
Lets you use classic Alt+Tab (window-based instead of app-based) in GNOME Shell.
This extension is obsolete since GNOME 3.30, see [this blogpost][alternatetab-post]
for further details.
[alternatetab-post]: https://blogs.gnome.org/fmuellner/2018/10/11/the-future-of-alternatetab-and-why-you-need-not-worry/
## Reporting bugs
Bugs should be reported to the [issue tracking system][bug-tracker].
The [GNOME handbook][bug-handbook] has useful information for creating
effective issue reports.
Please note that the issue tracker is meant to be used for
actionable issues only.
For support questions, feedback on changes or general discussions,
you can use:
- the [#gnome-shell matrix room][matrix-room]
- the `Desktop` category or `extensions` and `shell` tags on [GNOME Discourse][discourse]
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues
[bug-handbook]: https://handbook.gnome.org/issues/reporting.html
[matrix-room]: https://matrix.to/#/#gnome-shell:gnome.org
[discourse]: https://discourse.gnome.org
## Code of Conduct
All interactions with the project should follow the [Code of Conduct][conduct].
[conduct]: https://conduct.gnome.org/
The default development branch is `main`. If you still have a local
checkout under the old name, use:
```sh
git checkout master
git branch -m master main
git fetch
git branch --unset-upstream
git branch -u origin/master
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
```
## License
@@ -141,4 +89,8 @@ Public License, version 2 or later. See the [COPYING file][license] for details.
Individual extensions may be licensed under different terms, see each source
file for details.
[project-page]: https://wiki.gnome.org/Projects/GnomeShell/Extensions
[shell-page]: https://wiki.gnome.org/Projects/GnomeShell
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues
[license]: COPYING
[alternatetab-post]: https://blogs.gnome.org/fmuellner/2018/10/11/the-future-of-alternatetab-and-why-you-need-not-worry/

View File

@@ -1,48 +0,0 @@
# SPDX-FileCopyrightText: 2024 Florian Müllner <fmuellner@gnome.org>
# SPDX-License-Identifier: CC0-1.0
version = 1
SPDX-PackageName = "gnome-shell-extensions"
SPDX-PackageSupplier = "Florian Müllner <fmuellner@gnome.org>"
SPDX-PackageDownloadLocation = "https://gitlab.gnome.org/GNOME/gnome-shell-extensions"
[[annotations]]
path = "NEWS"
SPDX-FileCopyrightText = [
"2011 Giovanni Campagna <gcampagna@src.gnome.org>",
"2013 Florian Müllner <fmuellner@gnome.org>"
]
SPDX-License-Identifier = "CC-BY-SA-4.0"
[[annotations]]
path = [
"**.json.in",
"**.desktop.in",
"**.gschema.override",
"**.session",
"**.session.conf",
]
SPDX-FileCopyrightText = "Florian Müllner <fmuellner@gnome.org>"
SPDX-License-Identifier = "GPL-2.0-or-later"
[[annotations]]
# managed by translation teams
path = "po/**.po"
SPDX-FileCopyrightText = "GNOME Translation Teams <i18n@gnome.org>"
SPDX-License-Identifier = "GPL-2.0-or-later"
[[annotations]]
# managed by translation teams
path = ["po/LINGUAS", "po/POTFILES.in"]
SPDX-FileCopyrightText = "No rights reserved"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = "tools/package.json"
SPDX-FileCopyrightText = "2025 Florian Müllner <fmuellner@gnome.org>"
SPDX-License-Identifier = "MIT OR LGPL-2.0-or-later"
[[annotations]]
path = "**package-lock.json"
SPDX-FileCopyrightText = "No rights reserved"
SPDX-License-Identifier = "CC0-1.0"

2
data/HACKING Normal file
View File

@@ -0,0 +1,2 @@
To update the gnome-shell-sass submodule to latest upstream commit:
git submodule update --rebase

View File

@@ -5,6 +5,6 @@
"enabledExtensions": [@CLASSIC_EXTENSIONS@],
"panel": { "left": ["activities"],
"center": [],
"right": ["screenRecording", "screenSharing", "dwellClick", "a11y", "keyboard", "dateMenu", "quickSettings"]
"right": ["a11y", "keyboard", "dateMenu", "quickSettings"]
}
}

View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Name=GNOME Classic on Wayland
Comment=This session logs you into GNOME Classic
Exec=env GNOME_SHELL_SESSION_MODE=classic gnome-session
TryExec=gnome-session
Type=Application
DesktopNames=GNOME-Classic;GNOME;
X-GDM-SessionRegisters=true
X-GDM-CanRunHeadless=true

View File

@@ -0,0 +1,8 @@
[Desktop Entry]
Name=GNOME Classic on Xorg
Comment=This session logs you into GNOME Classic
Exec=env GNOME_SHELL_SESSION_MODE=classic gnome-session
TryExec=gnome-session
Type=Application
DesktopNames=GNOME-Classic;GNOME;
X-GDM-SessionRegisters=true

View File

@@ -1,7 +1,7 @@
[Desktop Entry]
Name=GNOME Classic
Comment=This session logs you into GNOME Classic
Exec=gnome-session --session gnome-classic
Exec=env GNOME_SHELL_SESSION_MODE=classic gnome-session
TryExec=gnome-session
Type=Application
DesktopNames=GNOME-Classic;GNOME;

View File

@@ -1,2 +0,0 @@
[GNOME Session]
Name=GNOME Classic

View File

@@ -1,3 +0,0 @@
[Unit]
Requires=gnome-session-services.target
Requires=org.gnome.Shell@classic.service

View File

@@ -2,16 +2,37 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
session_desktop = 'gnome-classic.desktop'
session_desktop_base = 'gnome-classic'
i18n.merge_file(
input: session_desktop + '.in',
output: session_desktop,
po_dir: '../po',
install: true,
install_dir: wlsessiondir,
type: 'desktop',
)
session_desktops = [
session_desktop_base,
session_desktop_base + '-xorg',
session_desktop_base + '-wayland',
]
foreach name : session_desktops
session_desktop = name + '.desktop'
if name.endswith('-xorg')
session_instdir = xsessiondir
elif name.endswith('-wayland')
session_instdir = wlsessiondir
else
# FIXME: The same target can not be copied into two directories.
# There is a workaround in meson/session-post-install.py until proper
# solution arises:
# https://github.com/mesonbuild/meson/issues/2416
session_instdir = xsessiondir
#session_instdir = [ xesssiondir, wlsessiondir ]
endif
i18n.merge_file(
input: session_desktop + '.in',
output: session_desktop,
po_dir: '../po',
install: true,
install_dir: session_instdir,
type: 'desktop',
)
endforeach
classic_uuids = []
foreach e : classic_extensions
@@ -31,13 +52,3 @@ configure_file(
classic_override = '00_org.gnome.shell.extensions.classic.gschema.override'
install_data(classic_override, install_dir: schemadir)
install_data(
'gnome-classic.session',
install_dir: sessiondir,
)
install_data(
'gnome-classic.session.conf',
install_dir: systemd_userunitdir / 'gnome-session@gnome-classic.target.d',
)

1133
debian/changelog vendored

File diff suppressed because it is too large Load Diff

289
debian/control vendored
View File

@@ -1,289 +0,0 @@
Source: gnome-shell-extensions
Standards-Version: 4.7.3
Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
Uploaders: Jeremy Bícha <jbicha@ubuntu.com>,
Laurent Bigonville <bigon@debian.org>,
Marco Trevisan (Treviño) <marco@ubuntu.com>
Section: gnome
Build-Depends: debhelper-compat (= 13),
dh-sequence-gnome,
dpkg-build-api (= 1),
libglib2.0-bin,
meson (>= 1.1.0),
sassc
Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-shell-extensions
Vcs-Git: https://salsa.debian.org/gnome-team/gnome-shell-extensions.git
Homepage: https://wiki.gnome.org/Projects/GnomeShell/Extensions
Package: gnome-shell-extensions
Architecture: all
Section: oldlibs
Depends: gnome-shell-extension-apps-menu,
gnome-shell-extension-auto-move-windows,
gnome-shell-extension-drive-menu,
gnome-shell-extension-launch-new-instance,
gnome-shell-extension-light-style,
gnome-shell-extension-native-window-placement,
gnome-shell-extension-places-menu,
gnome-shell-extension-screenshot-window-sizer,
gnome-shell-extension-status-icons,
gnome-shell-extension-system-monitor,
gnome-shell-extension-user-theme,
gnome-shell-extension-window-list,
gnome-shell-extension-windows-navigator,
gnome-shell-extension-workspace-indicator,
gnome-shell-extensions-common,
${misc:Depends}
Recommends: gnome-classic
Description: Extensions to extend functionality of GNOME Shell
GNOME Shell is extensible using extensions. This package contains
all the official GNOME Shell extensions.
.
This is an empty transitional package and will likely be removed
in the future.
Package: gnome-classic
Architecture: all
Depends: fonts-adwaita,
fonts-cantarell,
gnome-session,
gnome-session-bin (>= 46),
gnome-session-common (>= 46),
gnome-shell-extension-apps-menu,
gnome-shell-extension-launch-new-instance,
gnome-shell-extension-places-menu,
gnome-shell-extension-window-list,
xdg-desktop-portal-gnome,
${misc:Depends}
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: Classic version of the GNOME desktop
This package contains the required components for the GNOME Classic
session, based on the GNOME Shell. It can be started from a display
manager such as GDM, and requires 3D acceleration to work properly.
.
The GNOME Shell provides core interface functions like switching
windows, launching applications or see your notifications. It takes
advantage of the capabilities of modern graphics hardware and
introduces innovative user interface concepts to provide a
delightful and easy to use experience. GNOME Shell is the defining
technology of the GNOME user experience.
.
GNOME Classic provides an alternative version of GNOME Shell that uses
more traditional design elements.
Package: gnome-shell-extensions-common
Architecture: all
Multi-Arch: foreign
Depends: ${misc:Depends}
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: common files for official GNOME Shell extensions
GNOME Shell is extensible using extensions. This package contains
common data files such as translations for the official GNOME Shell
extensions.
Package: gnome-shell-extension-apps-menu
Architecture: all
Depends: gir1.2-gmenu-3.0,
gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: Category based app menu for GNOME Shell
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to add a category based Apps menu
similar to what is found in classic desktops.
.
This package is part of the GNOME Classic default set of extensions.
Package: gnome-shell-extension-auto-move-windows
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to move apps to specific workspaces
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to move apps to specific workspaces when
they create windows.
Package: gnome-shell-extension-drive-menu
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: Removable drive status menu for GNOME Shell
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to add a status menu for accessing and
unmounting removable devices.
Package: gnome-shell-extension-launch-new-instance
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to launch new instances of apps
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to always launch a new instance of an
app when clicking in the Dash or the application view.
.
This package is part of the GNOME Classic default set of extensions.
Package: gnome-shell-extension-light-style
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to switch the Shell to light style
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to switch GNOME Shell to use a light
style instead of the default.
Package: gnome-shell-extension-native-window-placement
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to arrange windows in a more compact way
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to arrange windows in the GNOME Shell
overview in a more compact way.
Package: gnome-shell-extension-places-menu
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: Places menu for GNOME Shell
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to add a menu for quickly navigating to
places in the system, similar to the menu in GNOME 2.
.
This package is part of the GNOME Classic default set of extensions.
Package: gnome-shell-extension-screenshot-window-sizer
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to resize windows for GNOME Software screenshots
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to resize windows to the recommended
size for creating screenshots for use in the GNOME Software app.
Package: gnome-shell-extension-status-icons
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Description: GNOME Shell extension to show some status icons in the top bar
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to show some status icons in the top bar.
Package: gnome-shell-extension-system-monitor
Architecture: all
Depends: gir1.2-gtop-2.0,
gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: Display system information in GNOME Shell status bar
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to display system information such as
memory usage, cpu usage, network rates and more in the top bar.
Package: gnome-shell-extension-user-theme
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to load alternative GNOME Shell themes
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to allow switching to alternative
GNOME Shell themes.
Package: gnome-shell-extension-window-list
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to display a window list
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to display a window list at the bottom
of the screen.
.
This package is part of the GNOME Classic default set of extensions.
Package: gnome-shell-extension-windows-navigator
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: GNOME Shell extension to allow keyboard selection in overlay mode
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to allow keyboard selections of windows
and workspaces in overlay mode. Ctrl+number selects a workspace and
Alt+number selects a window.
Package: gnome-shell-extension-workspace-indicator
Architecture: all
Depends: gnome-shell (<< ${gnome:NextVersion}),
gnome-shell (>= ${gnome:Version}),
gnome-shell-extensions-common (= ${source:Version}),
${misc:Depends}
Recommends: gnome-shell-extension-prefs | gnome-shell-extension-manager
Breaks: gnome-shell-extensions (<< 47)
Replaces: gnome-shell-extensions (<< 47)
Description: Workspace indicator for GNOME Shell
GNOME Shell is extensible using extensions. This package contains an
official GNOME Shell extension to add an indicator to the panel to
show what workspace you are using and allow you to switch to a different
workspace.

189
debian/copyright vendored
View File

@@ -1,189 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://download.gnome.org/sources/gnome-shell-extensions/
Files: *
Copyright: 2011-2013 Giovanni Campagna
2013-2024 Florian Müllner
2011 Iranian Free Software Users Group (IFSUG.org) translation team
2021-2022 Alexander Shopov
2011-2023 Red Hat, Inc
2013 Rosetta Contributors and Canonical Ltd
Free Software Foundation, Inc
Rūdofls Mazurs
Ville-Pekka Vainio
License: GPL-2+
Files: debian/*
Copyright: 2011 Victor Seva <linuxmaniac@torreviejawireless.org>
2011 Bilal Akhtar <bilalakhtar@ubuntu.com>
License: GPL-2+
Files: extensions/apps-menu/extension.js
Copyright: 2011 Giovanni Campagna
2011 Vamsi Krishna Brahmajosyula
2013 Debarshi Ray
2013 Florian Müllner
License: GPL-2+
Files: extensions/auto-move-windows/extension.js
Copyright: 2011 Alessandro Crismani
2011 Giovanni Campagna
2014 Florian Müllner
License: GPL-2+
Files: extensions/launch-new-instance/extension.js
Copyright: 2013 Florian Müllner
2013 Gabriel Rossetti
License: GPL-2+
Files: extensions/native-window-placement/extension.js
Copyright: 2011 Giovanni Campagna
2011 Stefano Facchini
2011 Wepmaschda
2015 Florian Müllner
License: GPL-2+
Files: extensions/places-menu/extension.js
Copyright: 2011 Giovanni Campagna
2011 Vamsi Krishna Brahmajosyula
2013 Florian Müllner
2016 Rémy Lefevre
License: GPL-2+
Files: extensions/places-menu/placeDisplay.js
Copyright: 2012 Giovanni Campagna
2013 Debarshi Ray
2015 Florian Müllner
2016 Rémy Lefevre
2017 Christian Kellner
License: GPL-2+
Files: extensions/screenshot-window-sizer/extension.js
Copyright: 2013 Owen Taylor
2013 Richard Hughes
2014 Florian Müllner
2016 Will Thompson
2017 Florian Müllner
2019 Adrien Plazas
2019 Willy Stadnick
License: GPL-2+
Files: extensions/status-icons/extension.js
Copyright: 2018 Adel Gadllah
2018 Florian Müllner
License: GPL-2+
Files: extensions/system-monitor/icons/*
Copyright: GNOME Design Team Icon Development Kit
License: CC0-1.0
Files: extensions/user-theme/extension.js
Copyright: 2011 Elad Alfassa
2011 Giovanni Campagna
2011 John Stowers
2014 Florian Müllner
License: GPL-2+
Files: extensions/window-list/prefs.js
Copyright: 2013 Florian Müllner
2014 Sylvain Pasche
License: GPL-2+
Files: extensions/window-list/stylesheet-light.css
extensions/workspace-indicator/stylesheet-light.css
Copyright: 2011-2013 Giovanni Campagna
2013-2024 Florian Müllner
License: GPL-2+
Files: extensions/windowsNavigator/extension.js
Copyright: 2011 Giovanni Campagna
2011, Maxim Ermilov
2017, Florian Müllner
2019, Marco Trevisan (Treviño)
2020, Thun Pin
License: GPL-2+
Files: extensions/windowsNavigator/stylesheet.css
Copyright: 2011 Maxim Ermilov
License: GPL-2+
Files: extensions/workspace-indicator/stylesheet-dark.css
Copyright: 2011 Erick Pérez Castellanos
2019 Florian Müllner
License: GPL-2+
Files: tools/run-eslint.sh
Copyright: 2020 Philip Chimento
2025 Florian Müllner
License: Expat or LGPL-2+
Files: tools/eslint.config.js
Copyright: 2020 Philip Chimento
2025 Florian Müllner
License: Expat or LGPL-2+
License: CC0-1.0
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
.
You should have received a copy of the CC0 Public Domain Dedication along with
this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
.
On Debian systems, the complete text of the CC0 1.0 Universal license can be
found in "/usr/share/common-licenses/CC0-1.0".
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License: GPL-2+
This package 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 package 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.
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
License: LGPL-2+
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
.
This library 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 Lesser General Public License
for more details.
.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <https://www.gnu.org/licenses/>.
Comment:
The oldest version of the Lesser General Public License under that name
was version 2.1.
.
On Debian systems, the full text of the GNU Lesser General Public License
version 2.1 can be found in the file /usr/share/common-licenses/LGPL-2.1,
and its predecessor the GNU Library General Public License version 2 can
be found in /usr/share/common-licenses/LGPL-2.

2
debian/docs vendored
View File

@@ -1,2 +0,0 @@
NEWS
README.md

17
debian/gbp.conf vendored
View File

@@ -1,17 +0,0 @@
[DEFAULT]
pristine-tar = True
debian-branch = debian/latest
upstream-branch = upstream/latest
[buildpackage]
sign-tags = True
[dch]
multimaint-merge = True
[import-orig]
postimport = dch -v%(version)s New upstream release; git add debian/changelog; debcommit
upstream-vcs-tag = %(version%~%.)s
[pq]
patch-numbers = False

View File

@@ -1,6 +0,0 @@
debian/local/gnome-session-classic usr/bin
usr/lib/systemd/user/gnome-session@gnome-classic.target.d/gnome-classic.session.conf
usr/share/glib-2.0/schemas/00_org.gnome.shell.extensions.classic.gschema.override
usr/share/gnome-session/sessions/gnome-classic.session
usr/share/gnome-shell/modes/classic.json
usr/share/wayland-sessions

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.apps-menu.gschema.xml
usr/share/gnome-shell/extensions/apps-menu@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.auto-move-windows.gschema.xml
usr/share/gnome-shell/extensions/auto-move-windows@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/gnome-shell/extensions/drive-menu@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/gnome-shell/extensions/launch-new-instance@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/gnome-shell/extensions/light-style@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.native-window-placement.gschema.xml
usr/share/gnome-shell/extensions/native-window-placement@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/gnome-shell/extensions/places-menu@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml
usr/share/gnome-shell/extensions/screenshot-window-sizer@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/gnome-shell/extensions/status-icons@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml
usr/share/gnome-shell/extensions/system-monitor@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.user-theme.gschema.xml
usr/share/gnome-shell/extensions/user-theme@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.window-list.gschema.xml
usr/share/gnome-shell/extensions/window-list@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/gnome-shell/extensions/windowsNavigator@gnome-shell-extensions.gcampax.github.com

View File

@@ -1,2 +0,0 @@
usr/share/glib-2.0/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
usr/share/gnome-shell/extensions/workspace-indicator@gnome-shell-extensions.gcampax.github.com

View File

@@ -1 +0,0 @@
usr/share/locale

View File

@@ -1,2 +0,0 @@
#! /bin/sh
env GNOME_SHELL_SESSION_MODE=classic gnome-session "$@"

View File

9
debian/rules vendored
View File

@@ -1,9 +0,0 @@
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_configure:
dh_auto_configure -- \
-Dextension_set=all \
-Dclassic_mode=true

View File

@@ -1 +0,0 @@
3.0 (quilt)

View File

@@ -1,5 +0,0 @@
---
Bug-Database: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues
Bug-Submit: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/new
Repository: https://gitlab.gnome.org/GNOME/gnome-shell-extensions.git
Repository-Browse: https://gitlab.gnome.org/GNOME/gnome-shell-extensions

4
debian/watch vendored
View File

@@ -1,4 +0,0 @@
version=4
opts="searchmode=plain, uversionmangle=s/\.(alpha|beta|rc)/~$1/, downloadurlmangle=s|cache.json||" \
https://download.gnome.org/sources/@PACKAGE@/cache.json \
[\d.]+/@PACKAGE@-([\d.]+\.?(?:alpha|beta|rc)?[\d.]*)@ARCHIVE_EXT@

View File

@@ -1 +0,0 @@
tools/eslint.config.js

View File

@@ -39,7 +39,7 @@ for f in $extensiondir/*; do
fi
cp $srcdir/NEWS $srcdir/COPYING $f
sources=(NEWS COPYING $(cd $f; ls *.js *.css 2>/dev/null))
sources=(NEWS COPYING $(cd $f; ls *.js))
[ -d $f/icons ] && sources+=(icons)

View File

@@ -44,11 +44,10 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
this._app = app;
this._button = button;
this._icon = this.getDragActor();
this._icon.style_class = 'icon-dropshadow';
this.add_child(this._icon);
this._iconBin = new St.Bin();
this.add_child(this._iconBin);
const appLabel = new St.Label({
let appLabel = new St.Label({
text: app.get_name(),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
@@ -56,17 +55,20 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
this.add_child(appLabel);
this.label_actor = appLabel;
this._delegate = this;
const draggable = DND.makeDraggable(this);
let textureCache = St.TextureCache.get_default();
textureCache.connectObject('icon-theme-changed',
() => this._updateIcon(), this);
this._updateIcon();
const maybeStartDrag = draggable._maybeStartDrag;
this._delegate = this;
let draggable = DND.makeDraggable(this);
let maybeStartDrag = draggable._maybeStartDrag;
draggable._maybeStartDrag = event => {
if (this._dragEnabled)
return maybeStartDrag.call(draggable, event);
return false;
};
this.connect('notify::active', this._onActiveChanged.bind(this));
}
activate(event) {
@@ -78,11 +80,10 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
Main.overview.hide();
}
_onActiveChanged() {
if (!this.active)
return;
this._button.scrollToButton(this);
setActive(active, params) {
if (active)
this._button.scrollToButton(this);
super.setActive(active, params);
}
setDragEnabled(enabled) {
@@ -94,7 +95,13 @@ class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
}
getDragActorSource() {
return this._icon;
return this._iconBin;
}
_updateIcon() {
let icon = this.getDragActor();
icon.style_class = 'icon-dropshadow';
this._iconBin.set_child(icon);
}
}
@@ -132,7 +139,7 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
}
_isNavigatingSubmenu([x, y]) {
const [posX, posY] = this.get_transformed_position();
let [posX, posY] = this.get_transformed_position();
if (this._oldX === -1) {
this._oldX = x;
@@ -140,8 +147,8 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
return true;
}
const deltaX = Math.abs(x - this._oldX);
const deltaY = Math.abs(y - this._oldY);
let deltaX = Math.abs(x - this._oldX);
let deltaY = Math.abs(y - this._oldY);
this._oldX = x;
this._oldY = y;
@@ -171,7 +178,7 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
// Ensure that the point P always lies below line AC so that we can
// only check for triangle ABC.
if (posY > y) {
const offset = posY - y;
let offset = posY - y;
y = posY + this.height + offset;
}
@@ -201,7 +208,7 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
this.hover = true;
if (this._isNavigatingSubmenu(event.get_coords()))
return Clutter.EVENT_STOP;
return true;
this._oldX = -1;
this._oldY = -1;
@@ -213,7 +220,7 @@ class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
if (targetActor instanceof St.Widget)
targetActor.sync_hover();
return Clutter.EVENT_PROPAGATE;
return false;
}
_onActiveChanged() {
@@ -294,15 +301,15 @@ class DesktopTarget extends EventEmitter {
}
async _markTrusted(file) {
const modeAttr = Gio.FILE_ATTRIBUTE_UNIX_MODE;
const trustedAttr = 'metadata::trusted';
const queryFlags = Gio.FileQueryInfoFlags.NONE;
const ioPriority = GLib.PRIORITY_DEFAULT;
let modeAttr = Gio.FILE_ATTRIBUTE_UNIX_MODE;
let trustedAttr = 'metadata::trusted';
let queryFlags = Gio.FileQueryInfoFlags.NONE;
let ioPriority = GLib.PRIORITY_DEFAULT;
try {
let info = await file.query_info_async(modeAttr, queryFlags, ioPriority, null);
const mode = info.get_attribute_uint32(modeAttr) | 0o100;
let mode = info.get_attribute_uint32(modeAttr) | 0o100;
info.set_attribute_uint32(modeAttr, mode);
info.set_attribute_string(trustedAttr, 'yes');
await file.set_attributes_async(info, queryFlags, ioPriority, null);
@@ -327,7 +334,7 @@ class DesktopTarget extends EventEmitter {
}
handleDragOver(source, _actor, _x, _y, _time) {
const appInfo = this._getSourceAppInfo(source);
let appInfo = this._getSourceAppInfo(source);
if (!appInfo)
return DND.DragMotionResult.CONTINUE;
@@ -335,16 +342,16 @@ class DesktopTarget extends EventEmitter {
}
acceptDrop(source, _actor, _x, _y, _time) {
const appInfo = this._getSourceAppInfo(source);
let appInfo = this._getSourceAppInfo(source);
if (!appInfo)
return false;
this.emit('app-dropped');
const desktop = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
let desktop = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
const src = Gio.File.new_for_path(appInfo.get_filename());
const dst = Gio.File.new_for_path(GLib.build_filenamev([desktop, src.get_basename()]));
let src = Gio.File.new_for_path(appInfo.get_filename());
let dst = Gio.File.new_for_path(GLib.build_filenamev([desktop, src.get_basename()]));
try {
// copy_async() isn't introspectable :-(
@@ -452,12 +459,12 @@ class ApplicationsButton extends PanelMenu.Button {
}
_onMenuKeyPress(actor, event) {
const symbol = event.get_key_symbol();
let symbol = event.get_key_symbol();
if (symbol === Clutter.KEY_Left || symbol === Clutter.KEY_Right) {
const direction = symbol === Clutter.KEY_Left
let direction = symbol === Clutter.KEY_Left
? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
if (this.menu.actor.navigate_focus(global.stage.key_focus, direction, false))
return Clutter.EVENT_STOP;
return true;
}
return super._onMenuKeyPress(actor, event);
}
@@ -480,15 +487,15 @@ class ApplicationsButton extends PanelMenu.Button {
}
_loadCategory(categoryId, dir) {
const iter = dir.iter();
let iter = dir.iter();
let nextType;
while ((nextType = iter.next()) !== GMenu.TreeItemType.INVALID) {
if (nextType === GMenu.TreeItemType.ENTRY) {
const entry = iter.get_entry();
let entry = iter.get_entry();
let id;
try {
id = entry.get_desktop_file_id(); // catch non-UTF8 filenames
} catch {
} catch (e) {
continue;
}
let app = appSys.lookup_app(id);
@@ -499,7 +506,7 @@ class ApplicationsButton extends PanelMenu.Button {
} else if (nextType === GMenu.TreeItemType.SEPARATOR) {
this.applicationsByCategory[categoryId].push('separator');
} else if (nextType === GMenu.TreeItemType.DIRECTORY) {
const subdir = iter.get_directory();
let subdir = iter.get_directory();
if (!subdir.get_is_nodisplay())
this._loadCategory(categoryId, subdir);
}
@@ -507,11 +514,11 @@ class ApplicationsButton extends PanelMenu.Button {
}
scrollToButton(button) {
const appsScrollBoxAdj = this.applicationsScrollBox.get_vadjustment();
const appsScrollBoxAlloc = this.applicationsScrollBox.get_allocation_box();
const currentScrollValue = appsScrollBoxAdj.get_value();
const boxHeight = appsScrollBoxAlloc.y2 - appsScrollBoxAlloc.y1;
const buttonAlloc = button.get_allocation_box();
let appsScrollBoxAdj = this.applicationsScrollBox.get_vadjustment();
let appsScrollBoxAlloc = this.applicationsScrollBox.get_allocation_box();
let currentScrollValue = appsScrollBoxAdj.get_value();
let boxHeight = appsScrollBoxAlloc.y2 - appsScrollBoxAlloc.y1;
let buttonAlloc = button.get_allocation_box();
let newScrollValue = currentScrollValue;
if (currentScrollValue > buttonAlloc.y1 - 10)
newScrollValue = buttonAlloc.y1 - 10;
@@ -522,11 +529,11 @@ class ApplicationsButton extends PanelMenu.Button {
}
scrollToCatButton(button) {
const catsScrollBoxAdj = this.categoriesScrollBox.get_vadjustment();
const catsScrollBoxAlloc = this.categoriesScrollBox.get_allocation_box();
const currentScrollValue = catsScrollBoxAdj.get_value();
const boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1;
const buttonAlloc = button.get_allocation_box();
let catsScrollBoxAdj = this.categoriesScrollBox.get_vadjustment();
let catsScrollBoxAlloc = this.categoriesScrollBox.get_allocation_box();
let currentScrollValue = catsScrollBoxAdj.get_value();
let boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1;
let buttonAlloc = button.get_allocation_box();
let newScrollValue = currentScrollValue;
if (currentScrollValue > buttonAlloc.y1 - 10)
newScrollValue = buttonAlloc.y1 - 10;
@@ -537,12 +544,10 @@ class ApplicationsButton extends PanelMenu.Button {
}
_createLayout() {
const section = new PopupMenu.PopupMenuSection();
let section = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(section);
this.mainBox = new St.BoxLayout({layoutManager: new MainLayout()});
this.leftBox = new St.BoxLayout({
orientation: Clutter.Orientation.VERTICAL,
});
this.leftBox = new St.BoxLayout({vertical: true});
this.applicationsScrollBox = new St.ScrollView({
style_class: 'apps-menu vfade',
x_expand: true,
@@ -552,13 +557,9 @@ class ApplicationsButton extends PanelMenu.Button {
});
this.leftBox.add_child(this.categoriesScrollBox);
this.applicationsBox = new St.BoxLayout({
orientation: Clutter.Orientation.VERTICAL,
});
this.applicationsBox = new St.BoxLayout({vertical: true});
this.applicationsScrollBox.set_child(this.applicationsBox);
this.categoriesBox = new St.BoxLayout({
orientation: Clutter.Orientation.VERTICAL,
});
this.categoriesBox = new St.BoxLayout({vertical: true});
this.categoriesScrollBox.set_child(this.categoriesBox);
this.mainBox.add_child(this.leftBox);
@@ -573,20 +574,20 @@ class ApplicationsButton extends PanelMenu.Button {
// Load categories
this.applicationsByCategory = {};
this._tree.load_sync();
const root = this._tree.get_root_directory();
let root = this._tree.get_root_directory();
let categoryMenuItem = new CategoryMenuItem(this, null);
this.categoriesBox.add_child(categoryMenuItem);
const iter = root.iter();
let iter = root.iter();
let nextType;
while ((nextType = iter.next()) !== GMenu.TreeItemType.INVALID) {
if (nextType !== GMenu.TreeItemType.DIRECTORY)
continue;
const dir = iter.get_directory();
let dir = iter.get_directory();
if (dir.get_is_nodisplay())
continue;
const categoryId = dir.get_menu_id();
let categoryId = dir.get_menu_id();
this.applicationsByCategory[categoryId] = [];
this._loadCategory(categoryId, dir);
if (this.applicationsByCategory[categoryId].length > 0) {
@@ -615,7 +616,7 @@ class ApplicationsButton extends PanelMenu.Button {
_displayButtons(apps) {
for (let i = 0; i < apps.length; i++) {
const app = apps[i];
let app = apps[i];
let item;
if (app instanceof Shell.App)
item = this._applicationsButtons.get(app);

View File

@@ -28,7 +28,7 @@ class WindowMover {
this._appConfigs.clear();
this._settings.get_strv('application-list').forEach(v => {
const [appId, num] = v.split(':');
let [appId, num] = v.split(':');
this._appConfigs.set(appId, parseInt(num) - 1);
});
@@ -36,15 +36,15 @@ class WindowMover {
}
_updateAppData() {
const ids = [...this._appConfigs.keys()];
const removedApps = [...this._appData.keys()]
let ids = [...this._appConfigs.keys()];
let removedApps = [...this._appData.keys()]
.filter(a => !ids.includes(a.id));
removedApps.forEach(app => {
app.disconnectObject(this);
this._appData.delete(app);
});
const addedApps = ids
let addedApps = ids
.map(id => this._appSystem.lookup_app(id))
.filter(app => app && !this._appData.has(app));
addedApps.forEach(app => {
@@ -68,7 +68,7 @@ class WindowMover {
return;
// ensure we have the required number of workspaces
const workspaceManager = global.workspace_manager;
let workspaceManager = global.workspace_manager;
for (let i = workspaceManager.n_workspaces; i <= workspaceNum; i++) {
window.change_workspace_by_index(i - 1, false);
workspaceManager.append_new_workspace(false, 0);
@@ -78,8 +78,8 @@ class WindowMover {
}
_appWindowsChanged(app) {
const data = this._appData.get(app);
const windows = app.get_windows();
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
@@ -89,7 +89,7 @@ class WindowMover {
return !windows.includes(w) && w.get_compositor_private() !== null;
}));
const workspaceNum = this._appConfigs.get(app.id);
let workspaceNum = this._appConfigs.get(app.id);
windows.filter(w => !data.windows.includes(w)).forEach(window => {
this._moveWindow(window, workspaceNum);
});

View File

@@ -5,7 +5,6 @@
import Adw from 'gi://Adw';
import Gio from 'gi://Gio';
import GioUnix from 'gi://GioUnix';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
@@ -43,11 +42,11 @@ class NewItemModel extends GObject.Object {
class Rule extends GObject.Object {
static [GObject.properties] = {
'app-info': GObject.ParamSpec.object(
'app-info', null, null,
'app-info', 'app-info', 'app-info',
GObject.ParamFlags.READWRITE,
GioUnix.DesktopAppInfo),
Gio.DesktopAppInfo),
'workspace': GObject.ParamSpec.uint(
'workspace', null, null,
'workspace', 'workspace', 'workspace',
GObject.ParamFlags.READWRITE,
1, WORKSPACE_MAX, 1),
};
@@ -119,7 +118,7 @@ class RulesList extends GObject.Object {
this.#rules = [];
for (const stringRule of this.#settings.get_strv(SETTINGS_KEY)) {
const [id, workspace] = stringRule.split(':');
const appInfo = GioUnix.DesktopAppInfo.new(id);
const appInfo = Gio.DesktopAppInfo.new(id);
if (appInfo)
this.#rules.push(new Rule({appInfo, workspace}));
else
@@ -194,7 +193,7 @@ class AutoMoveSettingsWidget extends Adw.PreferencesGroup {
class WorkspaceSelector extends Gtk.Widget {
static [GObject.properties] = {
'number': GObject.ParamSpec.uint(
'number', null, null,
'number', 'number', 'number',
GObject.ParamFlags.READWRITE,
1, WORKSPACE_MAX, 1),
};

View File

@@ -39,11 +39,11 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
this.mount = mount;
const ejectIcon = new St.Icon({
let ejectIcon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon',
});
const ejectButton = new St.Button({
let ejectButton = new St.Button({
child: ejectIcon,
style_class: 'button',
});
@@ -63,7 +63,7 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
if (this.mount.is_shadowed())
return false;
const volume = this.mount.get_volume();
let volume = this.mount.get_volume();
if (volume)
return volume.get_identifier('class') !== 'network';
@@ -87,7 +87,7 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
}
_eject() {
const unmountArgs = [
let unmountArgs = [
Gio.MountUnmountFlags.NONE,
new ShellMountOperation.ShellMountOperation(this.mount).mountOp,
null, // Gio.Cancellable
@@ -120,13 +120,13 @@ class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
_reportFailure(exception) {
// TRANSLATORS: %s is the filesystem name
const msg = _('Ejecting drive “%s” failed:').format(this.mount.get_name());
let msg = _('Ejecting drive “%s” failed:').format(this.mount.get_name());
Main.notifyError(msg, exception.message);
}
activate(event) {
const uri = this.mount.get_root().get_uri();
const context = global.create_app_launch_context(event.get_time(), -1);
let uri = this.mount.get_root().get_uri();
let context = global.create_app_launch_context(event.get_time(), -1);
Gio.AppInfo.launch_default_for_uri(uri, context);
super.activate(event);
@@ -141,7 +141,7 @@ class DriveMenu extends PanelMenu.Button {
constructor() {
super(0.5, _('Removable devices'));
const icon = new St.Icon({
let icon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'system-status-icon',
});
@@ -162,8 +162,8 @@ class DriveMenu extends PanelMenu.Button {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_('Open Files'), event => {
const appSystem = Shell.AppSystem.get_default();
const app = appSystem.lookup_app('org.gnome.Nautilus.desktop');
let appSystem = Shell.AppSystem.get_default();
let app = appSystem.lookup_app('org.gnome.Nautilus.desktop');
app.activate_full(-1, event.get_time());
});
@@ -178,7 +178,7 @@ class DriveMenu extends PanelMenu.Button {
}
_addMount(mount) {
const item = new MountMenuItem(mount);
let item = new MountMenuItem(mount);
this._mounts.unshift(item);
this.menu.addMenuItem(item, 0);
@@ -187,7 +187,7 @@ class DriveMenu extends PanelMenu.Button {
_removeMount(mount) {
for (let i = 0; i < this._mounts.length; i++) {
const item = this._mounts[i];
let item = this._mounts[i];
if (item.mount === mount) {
item.destroy();
this._mounts.splice(i, 1);

View File

@@ -3,7 +3,7 @@
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Launch New Instance",
"name": "Launch new instance",
"description": "Always launch a new instance when clicking in the dash or the application view.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME's GitLab instance instead.",
"shell-version": [ "@shell_current@" ],
"url": "@url@"

View File

@@ -29,7 +29,7 @@ class Rect {
}
union(rect2) {
const dest = this.copy();
let dest = this.copy();
if (rect2.x < dest.x) {
dest.width += dest.x - rect2.x;
dest.x = rect2.x;
@@ -47,7 +47,7 @@ class Rect {
}
adjusted(dx, dy, dx2, dy2) {
const dest = this.copy();
let dest = this.copy();
dest.x += dx;
dest.y += dy;
dest.width += -dx + dx2;
@@ -94,16 +94,16 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
// As we are using pseudo-random movement (See "slot") we need to make sure the list
// is always sorted the same way no matter which window is currently active.
const areaRect = new Rect(area.x, area.y, area.width, area.height);
let areaRect = new Rect(area.x, area.y, area.width, area.height);
let bounds = areaRect.copy();
const clones = layout.windows;
let clones = layout.windows;
let direction = 0;
const directions = [];
const rects = [];
let directions = [];
let rects = [];
for (let i = 0; i < clones.length; i++) {
// save rectangles into 4-dimensional arrays representing two corners of the rectangular: [left_x, top_y, right_x, bottom_y]
const rect = clones[i].boundingBox;
let rect = clones[i].boundingBox;
rects[i] = new Rect(rect.x, rect.y, rect.width, rect.height);
bounds = bounds.union(rects[i]);
@@ -120,10 +120,10 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
overlap = false;
for (let i = 0; i < rects.length; i++) {
for (let j = 0; j < rects.length; j++) {
const adjustments = [-1, -1, 1, 1]
let adjustments = [-1, -1, 1, 1]
.map(v => (v *= WINDOW_PLACEMENT_NATURAL_GAPS));
const iAdjusted = rects[i].adjusted(...adjustments);
const jAdjusted = rects[j].adjusted(...adjustments);
let iAdjusted = rects[i].adjusted(...adjustments);
let jAdjusted = rects[j].adjusted(...adjustments);
if (i !== j && iAdjusted.overlap(jAdjusted)) {
loopCounter++;
overlap = true;
@@ -132,8 +132,8 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
// Determine pushing direction
let iCenter = rects[i].center();
const jCenter = rects[j].center();
const diff = [jCenter[0] - iCenter[0], jCenter[1] - iCenter[1]];
let jCenter = rects[j].center();
let diff = [jCenter[0] - iCenter[0], jCenter[1] - iCenter[1]];
// Prevent dividing by zero and non-movement
if (diff[0] === 0 && diff[1] === 0)
@@ -210,7 +210,8 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
} while (overlap && loopCounter < WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS);
// Work out scaling by getting the most top-left and most bottom-right window coords.
const scale = Math.min(
let scale;
scale = Math.min(
areaRect.width / bounds.width,
areaRect.height / bounds.height,
1.0);
@@ -227,7 +228,7 @@ class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
// rescale to workspace
const slots = [];
let slots = [];
for (let i = 0; i < rects.length; i++) {
rects[i].x = rects[i].x * scale + areaRect.x;
rects[i].y = rects[i].y * scale + areaRect.y;

View File

@@ -74,7 +74,7 @@ class PlacesMenu extends PanelMenu.Button {
constructor() {
super(0.5, _('Places'));
const label = new St.Label({
let label = new St.Label({
text: _('Places'),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
@@ -86,7 +86,7 @@ class PlacesMenu extends PanelMenu.Button {
this._sections = { };
for (let i = 0; i < SECTIONS.length; i++) {
const id = SECTIONS[i];
let id = SECTIONS[i];
this._sections[id] = new PopupMenu.PopupMenuSection();
this.placesManager.connect(`${id}-updated`, () => {
this._redisplay(id);
@@ -110,7 +110,7 @@ class PlacesMenu extends PanelMenu.Button {
}
_create(id) {
const places = this.placesManager.get(id);
let places = this.placesManager.get(id);
for (let i = 0; i < places.length; i++)
this._sections[id].addMenuItem(new PlaceMenuItem(places[i]));

View File

@@ -23,6 +23,13 @@ Gio._promisify(Gio.File.prototype, 'mount_enclosing_volume');
const BACKGROUND_SCHEMA = 'org.gnome.desktop.background';
const Hostname1Iface = '<node> \
<interface name="org.freedesktop.hostname1"> \
<property name="PrettyHostname" type="s" access="read" /> \
</interface> \
</node>';
const Hostname1 = Gio.DBusProxy.makeProxyWrapper(Hostname1Iface);
class PlaceInfo extends EventEmitter {
constructor(...params) {
super();
@@ -56,7 +63,7 @@ class PlaceInfo extends EventEmitter {
const source = {
get_drive: () => null,
};
const op = new ShellMountOperation.ShellMountOperation(source);
let op = new ShellMountOperation.ShellMountOperation(source);
try {
await this.file.mount_enclosing_volume(0, op.mountOp, null);
@@ -72,7 +79,7 @@ class PlaceInfo extends EventEmitter {
}
launch(timestamp) {
const launchContext = global.create_app_launch_context(timestamp, -1);
let launchContext = global.create_app_launch_context(timestamp, -1);
this._ensureMountAndLaunch(launchContext, true).catch(logError);
}
@@ -83,7 +90,7 @@ class PlaceInfo extends EventEmitter {
null,
(file, result) => {
try {
const info = file.query_info_finish(result);
let info = file.query_info_finish(result);
this.icon = info.get_symbolic_icon();
this.emit('changed');
} catch (e) {
@@ -112,7 +119,7 @@ class PlaceInfo extends EventEmitter {
_getFileName() {
try {
const info = this.file.query_info('standard::display-name', 0, null);
let info = this.file.query_info('standard::display-name', 0, null);
return info.get_display_name();
} catch (e) {
if (e instanceof Gio.IOErrorEnum)
@@ -122,20 +129,44 @@ class PlaceInfo extends EventEmitter {
}
}
class NautilusSpecialInfo extends PlaceInfo {
constructor(file, name, icon) {
super('special', file, name, icon);
class RootInfo extends PlaceInfo {
_init() {
super._init('devices', Gio.File.new_for_path('/'), _('Computer'));
const appSystem = Shell.AppSystem.get_default();
this._app = appSystem.lookup_app('org.gnome.Nautilus.desktop');
let busName = 'org.freedesktop.hostname1';
let objPath = '/org/freedesktop/hostname1';
new Hostname1(Gio.DBus.system, busName, objPath, (obj, error) => {
if (error)
return;
this._proxy = obj;
this._proxy.connectObject('g-properties-changed',
this._propertiesChanged.bind(this), this);
this._propertiesChanged(obj);
});
}
launch(timestamp) {
const launchContext = global.create_app_launch_context(timestamp, -1);
this._app.appInfo.launch([this.file], launchContext);
getIcon() {
return new Gio.ThemedIcon({name: 'drive-harddisk-symbolic'});
}
_propertiesChanged(proxy) {
// GDBusProxy will emit a g-properties-changed when hostname1 goes down
// ignore it
if (proxy.g_name_owner) {
this.name = proxy.PrettyHostname || _('Computer');
this.emit('changed');
}
}
destroy() {
this._proxy?.disconnectObject(this);
this._proxy = null;
super.destroy();
}
}
class PlaceDeviceInfo extends PlaceInfo {
_init(kind, mount) {
this._mount = mount;
@@ -151,7 +182,7 @@ class PlaceDeviceInfo extends PlaceInfo {
}
eject() {
const unmountArgs = [
let unmountArgs = [
Gio.MountUnmountFlags.NONE,
new ShellMountOperation.ShellMountOperation(this._mount).mountOp,
null, // Gio.Cancellable
@@ -183,7 +214,7 @@ class PlaceDeviceInfo extends PlaceInfo {
}
_reportFailure(exception) {
const msg = _('Ejecting drive “%s” failed:').format(this._mount.get_name());
let msg = _('Ejecting drive “%s” failed:').format(this._mount.get_name());
Main.notifyError(msg, exception.message);
}
}
@@ -203,7 +234,7 @@ class PlaceVolumeInfo extends PlaceInfo {
this._volume.mount(0, null, null, (volume, result) => {
volume.mount_finish(result);
const mount = volume.get_mount();
let mount = volume.get_mount();
this.file = mount.get_root();
super.launch(timestamp);
});
@@ -214,6 +245,14 @@ class PlaceVolumeInfo extends PlaceInfo {
}
}
const DEFAULT_DIRECTORIES = [
GLib.UserDirectory.DIRECTORY_DOCUMENTS,
GLib.UserDirectory.DIRECTORY_PICTURES,
GLib.UserDirectory.DIRECTORY_MUSIC,
GLib.UserDirectory.DIRECTORY_DOWNLOAD,
GLib.UserDirectory.DIRECTORY_VIDEOS,
];
export class PlacesManager extends EventEmitter {
constructor() {
super();
@@ -228,12 +267,6 @@ export class PlacesManager extends EventEmitter {
this._settings = new Gio.Settings({schema_id: BACKGROUND_SCHEMA});
this._settings.connectObject('changed::show-desktop-icons',
() => this._updateSpecials(), this);
this._privacySettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.privacy',
});
this._privacySettings.connectObject('changed::remember-recent-files',
() => this._updateSpecials(), this);
this._updateSpecials();
/*
@@ -267,7 +300,7 @@ export class PlacesManager extends EventEmitter {
GLib.PRIORITY_DEFAULT, 100, () => {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return GLib.SOURCE_REMOVE;
return false;
});
});
@@ -279,9 +312,6 @@ export class PlacesManager extends EventEmitter {
this._settings?.disconnectObject(this);
this._settings = null;
this._privacySettings.disconnectObject(this);
this._privacySettings = null;
this._volumeMonitor.disconnectObject(this);
if (this._monitor)
@@ -290,92 +320,74 @@ export class PlacesManager extends EventEmitter {
GLib.source_remove(this._bookmarkTimeoutId);
}
_shouldShowRecent() {
const vfs = Gio.Vfs.get_default();
const schemes = vfs.get_supported_uri_schemes();
return this._privacySettings.get_boolean('remember-recent-files') &&
schemes.includes('recent');
}
_updateSpecials() {
this._places.special.forEach(p => p.destroy());
this._places.special = [];
const appSystem = Shell.AppSystem.get_default();
const nautilusApp = appSystem.lookup_app('org.gnome.Nautilus.desktop');
const defaultFm = Gio.AppInfo.get_default_for_type('inode/directory', true);
const showNautilusSpecials =
nautilusApp && defaultFm && nautilusApp.appInfo.equal(defaultFm);
const homeFile = Gio.File.new_for_path(GLib.get_home_dir());
let homePath = GLib.get_home_dir();
this._places.special.push(new PlaceInfo(
'special',
homeFile,
Gio.File.new_for_path(homePath),
_('Home')));
if (this._shouldShowRecent()) {
this._places.special.push(new PlaceInfo(
'special',
Gio.File.new_for_uri('recent:///'),
_('Recent')));
}
let specials = [];
let dirs = DEFAULT_DIRECTORIES.slice();
if (showNautilusSpecials) {
this._places.special.push(new NautilusSpecialInfo(
Gio.File.new_for_uri('starred:///'),
_('Starred'),
'starred-symbolic'));
}
if (this._settings.get_boolean('show-desktop-icons'))
dirs.push(GLib.UserDirectory.DIRECTORY_DESKTOP);
if (this._settings.get_boolean('show-desktop-icons')) {
const desktopPath = GLib.get_user_special_dir(
GLib.UserDirectory.DIRECTORY_DESKTOP);
const desktopFile = desktopPath
? Gio.File.new_for_path(desktopPath)
: null;
for (let i = 0; i < dirs.length; i++) {
let specialPath = GLib.get_user_special_dir(dirs[i]);
if (!specialPath || specialPath === homePath)
continue;
if (desktopFile && !desktopFile.equal(homeFile)) {
this._places.special.push(
new PlaceInfo('special', desktopFile));
let file = Gio.File.new_for_path(specialPath), info;
try {
info = new PlaceInfo('special', file);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue;
throw e;
}
specials.push(info);
}
if (showNautilusSpecials) {
this._places.special.push(new NautilusSpecialInfo(
Gio.File.new_for_uri('x-network-view:///'),
_('Network'),
'network-workgroup-symbolic'));
}
this._places.special.push(new PlaceInfo(
'special',
Gio.File.new_for_uri('trash:///'),
_('Trash')));
specials.sort((a, b) => GLib.utf8_collate(a.name, b.name));
this._places.special = this._places.special.concat(specials);
this.emit('special-updated');
}
_updateMounts() {
const networkMounts = [];
const networkVolumes = [];
let networkMounts = [];
let networkVolumes = [];
this._places.devices.forEach(p => p.destroy());
this._places.devices = [];
this._places.network.forEach(p => p.destroy());
this._places.network = [];
/* Add standard places */
this._places.devices.push(new RootInfo());
this._places.network.push(new PlaceInfo(
'network',
Gio.File.new_for_uri('network:///'),
_('Browse Network'),
'network-workgroup-symbolic'));
/* first go through all connected drives */
const drives = this._volumeMonitor.get_connected_drives();
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
const volumes = drives[i].get_volumes();
let volumes = drives[i].get_volumes();
for (let j = 0; j < volumes.length; j++) {
const identifier = volumes[j].get_identifier('class');
let identifier = volumes[j].get_identifier('class');
if (identifier && identifier.includes('network')) {
networkVolumes.push(volumes[j]);
} else {
const mount = volumes[j].get_mount();
let mount = volumes[j].get_mount();
if (mount)
this._addMount('devices', mount);
}
@@ -383,23 +395,23 @@ export class PlacesManager extends EventEmitter {
}
/* add all volumes that is not associated with a drive */
const volumes = this._volumeMonitor.get_volumes();
let volumes = this._volumeMonitor.get_volumes();
for (let i = 0; i < volumes.length; i++) {
if (volumes[i].get_drive())
continue;
const identifier = volumes[i].get_identifier('class');
let identifier = volumes[i].get_identifier('class');
if (identifier && identifier.includes('network')) {
networkVolumes.push(volumes[i]);
} else {
const mount = volumes[i].get_mount();
let mount = volumes[i].get_mount();
if (mount)
this._addMount('devices', mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
const mounts = this._volumeMonitor.get_mounts();
let mounts = this._volumeMonitor.get_mounts();
for (let i = 0; i < mounts.length; i++) {
if (mounts[i].is_shadowed())
continue;
@@ -407,7 +419,7 @@ export class PlacesManager extends EventEmitter {
if (mounts[i].get_volume())
continue;
const root = mounts[i].get_default_location();
let root = mounts[i].get_default_location();
if (!root.is_native()) {
networkMounts.push(mounts[i]);
continue;
@@ -416,7 +428,7 @@ export class PlacesManager extends EventEmitter {
}
for (let i = 0; i < networkVolumes.length; i++) {
const mount = networkVolumes[i].get_mount();
let mount = networkVolumes[i].get_mount();
if (mount) {
networkMounts.push(mount);
continue;
@@ -433,7 +445,7 @@ export class PlacesManager extends EventEmitter {
}
_findBookmarksFile() {
const paths = [
let paths = [
GLib.build_filenamev([GLib.get_user_config_dir(), 'gtk-3.0', 'bookmarks']),
GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']),
];
@@ -449,19 +461,19 @@ export class PlacesManager extends EventEmitter {
_reloadBookmarks() {
this._bookmarks = [];
const content = Shell.get_file_contents_utf8_sync(this._bookmarksFile.get_path());
const lines = content.split('\n');
let content = Shell.get_file_contents_utf8_sync(this._bookmarksFile.get_path());
let lines = content.split('\n');
const bookmarks = [];
let bookmarks = [];
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const components = line.split(' ');
const [bookmark] = components;
let line = lines[i];
let components = line.split(' ');
let [bookmark] = components;
if (!bookmark)
continue;
const file = Gio.File.new_for_uri(bookmark);
let file = Gio.File.new_for_uri(bookmark);
if (file.is_native() && !file.query_exists(null))
continue;
@@ -496,12 +508,30 @@ export class PlacesManager extends EventEmitter {
}
_addMount(kind, mount) {
const devItem = new PlaceDeviceInfo(kind, mount);
let devItem;
try {
devItem = new PlaceDeviceInfo(kind, mount);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
return;
throw e;
}
this._places[kind].push(devItem);
}
_addVolume(kind, volume) {
const volItem = new PlaceVolumeInfo(kind, volume);
let volItem;
try {
volItem = new PlaceVolumeInfo(kind, volume);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
return;
throw e;
}
this._places[kind].push(volItem);
}

View File

@@ -63,22 +63,21 @@ export default class ScreenshotWindowSizerExtension extends Extension {
/**
* @param {Meta.Display} display - the display
* @param {Meta.Window=} window - for per-window bindings, the window
* @param {Clutter.Event} event - the triggering event
* @param {Meta.KeyBinding} binding - the key binding
*/
_cycleScreenshotSizes(display, window, event, binding) {
_cycleScreenshotSizes(display, window, binding) {
const backwards = binding.is_reversed();
// Unmaximize first
if (window.is_maximized())
window.unmaximize();
if (window.get_maximized() !== 0)
window.unmaximize(Meta.MaximizeFlags.BOTH);
const workArea = window.get_work_area_current_monitor();
const outerRect = window.get_frame_rect();
let workArea = window.get_work_area_current_monitor();
let outerRect = window.get_frame_rect();
// Double both axes if on a hidpi display
const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
const scaledSizes = this.SIZES.map(size => size.map(wh => wh * scaleFactor))
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let scaledSizes = this.SIZES.map(size => size.map(wh => wh * scaleFactor))
.filter(([w, h]) => w <= workArea.width && h <= workArea.height);
// Find the nearest 16:9 size for the current window size
@@ -86,10 +85,10 @@ export default class ScreenshotWindowSizerExtension extends Extension {
let nearestError;
for (let i = 0; i < scaledSizes.length; i++) {
const [width, height] = scaledSizes[i];
let [width, height] = scaledSizes[i];
// get the best initial window size
const error = Math.abs(width - outerRect.width) + Math.abs(height - outerRect.height);
let error = Math.abs(width - outerRect.width) + Math.abs(height - outerRect.height);
if (nearestIndex === undefined || error < nearestError) {
nearestIndex = i;
nearestError = error;
@@ -97,8 +96,8 @@ export default class ScreenshotWindowSizerExtension extends Extension {
}
// get the next size up or down from ideal
const newIndex = (nearestIndex + (backwards ? -1 : 1)) % scaledSizes.length;
const [newWidth, newHeight] = scaledSizes.at(newIndex);
let newIndex = (nearestIndex + (backwards ? -1 : 1)) % scaledSizes.length;
let [newWidth, newHeight] = scaledSizes.at(newIndex);
// Push the window onscreen if it would be resized offscreen
let newX = outerRect.x;
@@ -120,7 +119,7 @@ export default class ScreenshotWindowSizerExtension extends Extension {
*/
_notifySizeChange(window) {
const {scaleFactor} = St.ThemeContext.get_for_stage(global.stage);
const newOuterRect = window.get_frame_rect();
let newOuterRect = window.get_frame_rect();
let message = '%d×%d'.format(
newOuterRect.width / scaleFactor,
newOuterRect.height / scaleFactor);
@@ -128,7 +127,7 @@ export default class ScreenshotWindowSizerExtension extends Extension {
// The new size might have been constrained by geometry hints (e.g. for
// a terminal) - in that case, include the actual ratio to the message
// we flash
const actualNumerator = 9 * newOuterRect.width / newOuterRect.height;
let actualNumerator = 9 * newOuterRect.width / newOuterRect.height;
if (Math.abs(actualNumerator - 16) > 0.01)
message += ' (%.2f:9)'.format(actualNumerator);

View File

@@ -4,7 +4,7 @@
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Screenshot Window Sizer",
"description": "Resize windows for GNOME Software screenshots with Ctrl+Alt+s shortcut",
"description": "Resize windows for GNOME Software screenshots",
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -1,91 +0,0 @@
// SPDX-FileCopyrightText: 2018 Adel Gadllah <adel.gadllah@gmail.com>
// SPDX-FileCopyrightText: 2018 Florian Müllner <fmuellner@gnome.org>
//
// SPDX-License-Identifier: GPL-2.0-or-later
import Clutter from 'gi://Clutter';
import Shell from 'gi://Shell';
import St from 'gi://St';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import {Button as PanelButton} from 'resource:///org/gnome/shell/ui/panelMenu.js';
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',
];
export default class SysTray {
constructor() {
this._icons = new Map();
this._tray = null;
}
_onTrayIconAdded(o, icon) {
const wmClass = icon.wm_class ? icon.wm_class.toLowerCase() : '';
if (STANDARD_TRAY_ICON_IMPLEMENTATIONS.includes(wmClass))
return;
const button = new PanelButton(0.5, null, true);
const scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
const iconSize = PANEL_ICON_SIZE * scaleFactor;
icon.set({
width: iconSize,
height: iconSize,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
const iconBin = new St.Widget({
layout_manager: new Clutter.BinLayout(),
style_class: 'system-status-icon',
});
iconBin.add_child(icon);
button.add_child(iconBin);
this._icons.set(icon, button);
button.connect('button-release-event',
(actor, event) => icon.click(event));
button.connect('key-press-event',
(actor, event) => icon.click(event));
const role = `${icon}`;
Main.panel.addToStatusArea(role, button);
}
_onTrayIconRemoved(o, icon) {
const button = this._icons.get(icon);
button?.destroy();
this._icons.delete(icon);
}
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);
}
disable() {
this._icons.forEach(button => button.destroy());
this._icons.clear();
this._tray.unmanage_screen();
this._tray = null;
}
}

View File

@@ -1,9 +0,0 @@
# SPDX-FileCopyrightText: 2018 Florian Müllner <fmuellner@gnome.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)

View File

@@ -1,10 +0,0 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Status Icons",
"description": "Show status icons in the top bar",
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -361,7 +361,6 @@ class Indicator extends PanelMenu.Button {
}
constructor(settings) {
GTop.glibtop_init();
super(0.5, _('System stats'));
this._settings = settings;

View File

@@ -33,7 +33,7 @@ export default class ThemeManager extends Extension {
_changeTheme() {
let stylesheet = null;
const themeName = this._settings.get_string(SETTINGS_KEY);
let themeName = this._settings.get_string(SETTINGS_KEY);
if (themeName) {
const stylesheetPaths = getThemeDirs()
@@ -43,7 +43,7 @@ export default class ThemeManager extends Extension {
.map(dir => `${dir}/${themeName}.css`));
stylesheet = stylesheetPaths.find(path => {
const file = Gio.file_new_for_path(path);
let file = Gio.file_new_for_path(path);
return file.query_exists(null);
});
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,33 +12,5 @@ extension_data += files(
'stylesheet-light.css'
)
transform_stylesheet = [
'sed', '-E',
'-e', 's:^\.(workspace-indicator):.window-list-\\1:',
'-e', '/^@import/d',
'@INPUT@',
]
workspaceIndicatorSources = [
configure_file(
input: '../workspace-indicator/workspaceIndicator.js',
output: '@PLAINNAME@',
copy: true,
),
configure_file(
input: '../workspace-indicator/stylesheet-dark.css',
output: 'stylesheet-workspace-switcher-dark.css',
command: transform_stylesheet,
capture: true,
),
configure_file(
input: '../workspace-indicator/stylesheet-light.css',
output: 'stylesheet-workspace-switcher-light.css',
command: transform_stylesheet,
capture: true,
),
files('../workspace-indicator/workspacePrefs.js'),
]
extension_sources += files('prefs.js') + workspaceIndicatorSources
extension_sources += files('prefs.js', 'workspaceIndicator.js')
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -36,9 +36,5 @@ SPDX-License-Identifier: GPL-2.0-or-later
only on the primary one.
</description>
</key>
<key name="embed-previews" type="b">
<default>true</default>
<summary>Show workspace previews in window list</summary>
</key>
</schema>
</schemalist>

View File

@@ -11,18 +11,13 @@ import Gtk from 'gi://Gtk';
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import {WorkspacesPage} from './workspacePrefs.js';
class WindowListPage extends Adw.PreferencesPage {
class WindowListPrefsWidget extends Adw.PreferencesPage {
static {
GObject.registerClass(this);
}
constructor(settings) {
super({
title: _('Window List'),
icon_name: 'focus-windows-symbolic',
});
super();
this._actionGroup = new Gio.SimpleActionGroup();
this.insert_action_group('window-list', this._actionGroup);
@@ -34,8 +29,6 @@ class WindowListPage extends Adw.PreferencesPage {
this._settings.create_action('show-on-all-monitors'));
this._actionGroup.add_action(
this._settings.create_action('display-all-workspaces'));
this._actionGroup.add_action(
this._settings.create_action('embed-previews'));
const groupingGroup = new Adw.PreferencesGroup({
title: _('Window Grouping'),
@@ -64,24 +57,34 @@ class WindowListPage extends Adw.PreferencesPage {
const miscGroup = new Adw.PreferencesGroup();
this.add(miscGroup);
let row = new Adw.SwitchRow({
title: _('Show on all monitors'),
let toggle = new Gtk.Switch({
action_name: 'window-list.show-on-all-monitors',
valign: Gtk.Align.CENTER,
});
let row = new Adw.ActionRow({
title: _('Show on all monitors'),
activatable_widget: toggle,
});
row.add_suffix(toggle);
miscGroup.add(row);
row = new Adw.SwitchRow({
title: _('Show windows from all workspaces'),
toggle = new Gtk.Switch({
action_name: 'window-list.display-all-workspaces',
valign: Gtk.Align.CENTER,
});
this._settings.bind('display-all-workspaces',
toggle, 'active', Gio.SettingsBindFlags.DEFAULT);
row = new Adw.ActionRow({
title: _('Show windows from all workspaces'),
activatable_widget: toggle,
});
row.add_suffix(toggle);
miscGroup.add(row);
}
}
export default class WindowListPrefs extends ExtensionPreferences {
fillPreferencesWindow(window) {
const settings = this.getSettings();
window.add(new WindowListPage(settings));
window.add(new WorkspacesPage(settings));
getPreferencesWidget() {
return new WindowListPrefsWidget(this.getSettings());
}
}

View File

@@ -4,12 +4,6 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@import url("stylesheet-workspace-switcher-dark.css");
.window-list-workspace-indicator.previews {
-natural-hpadding: 0 !important;
-minimum-hpadding: 0 !important;
}
.window-list {
spacing: 2px;
@@ -22,19 +16,10 @@
height: 2.45em;
}
.window-button,
.window-button-drag-actor {
.window-button {
padding: 4px, 3px;
}
.window-button-drag-actor {
background-color: #444;
border-radius: 7px;
border-width: 2px;
border-color: #fff;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.window-button:first-child:ltr {
padding-left: 2px;
}
@@ -48,45 +33,38 @@
}
.window-button > StWidget {
color: #fff;
background-color: transparent;
color: #bbb;
background-color: #1d1d1d;
border-radius: 4px;
padding: 3px 6px 1px;
transition: 100ms ease;
}
.window-button > StWidget,
.window-list .placeholder {
.window-button > StWidget {
-st-natural-width: 18.75em;
max-width: 18.75em;
}
.window-list .placeholder {
border: 1px solid rgba(255,255,255,0.4);
border-radius: 7px;
margin: 4px;
}
.window-button:hover > StWidget {
color: #fff;
background-color: #303030;
}
.window-button:active > StWidget,
.window-button:focus > StWidget {
background-color: st-lighten(#303030, 5%);
color: #fff;
background-color: #3f3f3f;
}
.window-button.focused > StWidget {
background-color: #5b5b5b;
color: #fff;
background-color: #3f3f3f;
}
.window-button.focused:hover > StWidget {
background-color: st-lighten(#5b5b5b, 5%);
}
.window-button.focused:active > StWidget {
background-color: st-lighten(#5b5b5b, 10%);
}
.window-button.focused:active > StWidget {
color: #fff;
background-color: #3f3f3f;
}
.window-button.minimized > StWidget {
color: #666;
@@ -103,17 +81,36 @@
height: 24px;
}
.window-button-abstract-label {
background-color: #888;
border-radius: 99px;
margin: 6px;
.window-list-workspace-indicator .status-label-bin {
background-color: rgba(200, 200, 200, 0.3);
padding: 5px;
margin: 3px;
}
.window-button-attention-indicator {
background-color: -st-accent-color;
height: 2px;
.window-list-workspace-indicator .workspaces-box {
spacing: 3px;
padding: 5px;
}
.window-button.minimized .window-button-attention-indicator {
background-color: st-transparentize(-st-accent-color, 0.4);
.window-list-workspace-indicator .workspace {
width: 52px;
border-radius: 4px;
background-color: #1e1e1e;
}
.window-list-workspace-indicator .workspace.active {
background-color: #3f3f3f;
}
.window-list-window-preview {
background-color: #bebebe;
border-radius: 1px;
}
.window-list-window-preview.active {
background-color: #d4d4d4;
}
.notification {
font-weight: normal;
}

View File

@@ -6,7 +6,6 @@
*/
@import url("stylesheet-dark.css");
@import url("stylesheet-workspace-switcher-light.css");
#panel.bottom-panel {
border-top-width: 1px;
@@ -15,52 +14,58 @@
}
.bottom-panel .window-button > StWidget {
color: #2e3436;
background-color: #eee;
border-radius: 3px;
padding: 3px 6px 1px;
box-shadow: none;
text-shadow: none;
border: 1px solid rgba(0,0,0,0.2);
}
.window-button > StWidget {
color: #000;
}
.window-button:hover > StWidget {
background-color: st-darken(#eee,5%);
}
.window-button:active > StWidget,
.window-button:focus > StWidget {
background-color: st-darken(#eee, 10%);
}
.window-button.focused > StWidget {
background-color: st-darken(#eee,15%);
}
.window-button.focused:hover > StWidget {
background-color: st-darken(#eee, 20%);
.bottom-panel .window-button > StWidget {
-st-natural-width: 18.7em;
max-width: 18.75em;
}
.window-button.focused:active > StWidget {
background-color: st-darken(#eee, 25%);
.bottom-panel .window-button:hover > StWidget {
background-color: #f9f9f9;
}
.window-button.minimized > StWidget {
color: #aaa;
background-color: #f9f9f9;
.bottom-panel .window-button:active > StWidget,
.bottom-panel .window-button:focus > StWidget {
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
.bottom-panel .window-button.focused > StWidget {
background-color: #ccc;
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
.bottom-panel .window-button.focused:hover > StWidget {
background-color: #e9e9e9;
}
.bottom-panel .window-button.minimized > StWidget {
color: #888;
box-shadow: none;
}
/* workspace switcher */
.window-list-workspace-indicator .workspace {
border: 2px solid #f6f5f4;
background-color: #ccc;
}
.window-button.minimized:active > StWidget {
color: #aaa;
background-color: #f9f9f9;
.window-list-workspace-indicator .workspace.active {
border-color: #888;
}
.window-button-drag-actor {
background-color: #ddd;
border-color: #888;
.window-list-window-preview {
background-color: #ededed;
border: 1px solid #ccc;
}
.window-list .placeholder {
border-color: rgba(0,0,0,0.5);
.window-list-window-preview.active {
background-color: #f6f5f4;
}

View File

@@ -0,0 +1,430 @@
// SPDX-FileCopyrightText: 2019 Florian Müllner <fmuellner@gnome.org>
//
// SPDX-License-Identifier: GPL-2.0-or-later
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Meta from 'gi://Meta';
import St from 'gi://St';
import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
const TOOLTIP_OFFSET = 6;
const TOOLTIP_ANIMATION_TIME = 150;
const MAX_THUMBNAILS = 6;
class WindowPreview extends St.Button {
static {
GObject.registerClass(this);
}
constructor(window) {
super({
style_class: 'window-list-window-preview',
});
this._delegate = this;
DND.makeDraggable(this, {restoreOnSuccess: true});
this._window = window;
this._window.connectObject(
'size-changed', () => this._checkRelayout(),
'position-changed', () => this._checkRelayout(),
'notify::minimized', this._updateVisible.bind(this),
'notify::skip-taskbar', this._updateVisible.bind(this),
this);
this._updateVisible();
global.display.connectObject('notify::focus-window',
this._onFocusChanged.bind(this), this);
this._onFocusChanged();
}
// needed for DND
get metaWindow() {
return this._window;
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_checkRelayout() {
const monitor = Main.layoutManager.findIndexForActor(this);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
if (this._window.get_frame_rect().overlap(workArea))
this.queue_relayout();
}
_updateVisible() {
this.visible = !this._window.skip_taskbar &&
this._window.showing_on_its_workspace();
}
}
class WorkspaceLayout extends Clutter.LayoutManager {
static {
GObject.registerClass(this);
}
vfunc_get_preferred_width() {
return [0, 0];
}
vfunc_get_preferred_height() {
return [0, 0];
}
vfunc_allocate(container, box) {
const monitor = Main.layoutManager.findIndexForActor(container);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
const hscale = box.get_width() / workArea.width;
const vscale = box.get_height() / workArea.height;
for (const child of container) {
const childBox = new Clutter.ActorBox();
const frameRect = child.metaWindow.get_frame_rect();
childBox.set_size(
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
childBox.set_origin(
Math.round((frameRect.x - workArea.x) * hscale),
Math.round((frameRect.y - workArea.y) * vscale));
child.allocate(childBox);
}
}
}
class WorkspaceThumbnail extends St.Button {
static {
GObject.registerClass(this);
}
constructor(index) {
super({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new WorkspaceLayout(),
clip_to_allocation: true,
x_expand: true,
y_expand: 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
this._windowPreviews = new Map();
let workspaceManager = global.workspace_manager;
this._workspace = workspaceManager.get_workspace_by_index(index);
this._workspace.connectObject(
'window-added', (ws, window) => this._addWindow(window),
'window-removed', (ws, window) => this._removeWindow(window),
this);
global.display.connectObject('restacked',
this._onRestacked.bind(this), this);
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
acceptDrop(source) {
if (!source.metaWindow)
return false;
this._moveWindow(source.metaWindow);
return true;
}
handleDragOver(source) {
if (source.metaWindow)
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);
}
on_clicked() {
let ws = global.workspace_manager.get_workspace_by_index(this._index);
if (ws)
ws.activate(global.get_current_time());
}
_syncTooltip() {
if (this.hover) {
this._tooltip.set({
text: Meta.prefs_get_workspace_name(this._index),
visible: true,
opacity: 0,
});
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.clamp(
stageX + xOffset,
monitor.x,
monitor.x + monitor.width - tipWidth);
const y = stageY - tipHeight - TOOLTIP_OFFSET;
this._tooltip.set_position(x, y);
}
this._tooltip.ease({
opacity: this.hover ? 255 : 0,
duration: TOOLTIP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => (this._tooltip.visible = this.hover),
});
}
_onDestroy() {
this._tooltip.destroy();
}
}
export class WorkspaceIndicator extends PanelMenu.Button {
static {
GObject.registerClass(this);
}
constructor() {
super(0.5, _('Workspace Indicator'), true);
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
this.add_style_class_name('window-list-workspace-indicator');
this.remove_style_class_name('panel-button');
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_child(container);
let workspaceManager = global.workspace_manager;
this._currentWorkspace = workspaceManager.get_active_workspace_index();
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_child(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_child(this._thumbnailsBox);
this._workspacesItems = [];
workspaceManager.connectObject(
'notify::n-workspaces', this._nWorkspacesChanged.bind(this), GObject.ConnectFlags.AFTER,
'workspace-switched', this._onWorkspaceSwitched.bind(this), GObject.ConnectFlags.AFTER,
'notify::layout-rows', this._updateThumbnailVisibility.bind(this),
this);
this.connect('scroll-event', this._onScrollEvent.bind(this));
this._updateMenu();
this._updateThumbnails();
this._updateThumbnailVisibility();
this._settings = new Gio.Settings({schema_id: 'org.gnome.desktop.wm.preferences'});
this._settings.connectObject('changed::workspace-names',
() => this._updateMenuLabels(), this);
}
_updateThumbnailVisibility() {
const {workspaceManager} = global;
const vertical = workspaceManager.layout_rows === -1;
const useMenu =
vertical || workspaceManager.n_workspaces > MAX_THUMBNAILS;
this.reactive = useMenu;
this._statusBin.visible = useMenu;
this._thumbnailsBox.visible = !useMenu;
}
_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();
this._updateThumbnailVisibility();
}
_updateMenuOrnament() {
for (let i = 0; i < this._workspacesItems.length; i++) {
this._workspacesItems[i].setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NO_DOT);
}
}
_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();
let total = workspaceManager.n_workspaces;
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;
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', () => {
this._activate(item.workspaceId);
});
item.setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NO_DOT);
this.menu.addMenuItem(item);
this._workspacesItems[i] = item;
}
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_child(thumb);
}
this._updateActiveThumbnail();
}
_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);
}
}

View File

@@ -147,7 +147,7 @@ export default class Extension {
/* eslint-disable no-invalid-this */
return function () {
const {layoutManager} = this._container;
for (const i in layoutManager._windowSlots) {
for (let i in layoutManager._windowSlots) {
if (layoutManager._windowSlots[i])
layoutManager._windowSlots[i][WINDOW_SLOT].hideTooltip();
}
@@ -173,7 +173,7 @@ export default class Extension {
this._injectionManager.overrideMethod(viewProto, '_hideTooltips', () => {
/* eslint-disable no-invalid-this */
return function () {
if (global.stage.get_key_focus() === null)
if (global.stage.get_key_focus() === global.stage)
global.stage.set_key_focus(this._prevFocusActor);
this._pickWindow = false;
for (let i = 0; i < this._workspaces.length; i++)
@@ -210,9 +210,9 @@ export default class Extension {
return function (actor, event) {
const {ControlsState} = OverviewControls;
if (this._overviewAdjustment.value !== ControlsState.WINDOW_PICKER)
return Clutter.EVENT_PROPAGATE;
return false;
const workspaceManager = global.workspace_manager;
let workspaceManager = global.workspace_manager;
if ((event.get_key_symbol() === Clutter.KEY_Alt_L ||
event.get_key_symbol() === Clutter.KEY_Alt_R) &&
@@ -222,7 +222,7 @@ export default class Extension {
this._active = workspaceManager.get_active_workspace_index();
this._pickWindow = true;
this._workspaces[workspaceManager.get_active_workspace_index()].showWindowsTooltips();
return Clutter.EVENT_STOP;
return true;
}
if ((event.get_key_symbol() === Clutter.KEY_Control_L ||
event.get_key_symbol() === Clutter.KEY_Control_R) &&
@@ -232,22 +232,22 @@ export default class Extension {
this._pickWorkspace = true;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].showTooltip();
return Clutter.EVENT_STOP;
return true;
}
if (global.stage.get_key_focus() !== null)
return Clutter.EVENT_PROPAGATE;
if (global.stage.get_key_focus() !== global.stage)
return false;
// ignore shift presses, they're required to get numerals in azerty keyboards
if ((this._pickWindow || this._pickWorkspace) &&
(event.get_key_symbol() === Clutter.KEY_Shift_L ||
event.get_key_symbol() === Clutter.KEY_Shift_R))
return Clutter.EVENT_STOP;
return true;
if (this._pickWindow) {
if (this._active !== workspaceManager.get_active_workspace_index()) {
this._hideTooltips();
return Clutter.EVENT_PROPAGATE;
return false;
}
let c = event.get_key_symbol() - Clutter.KEY_KP_0;
@@ -256,17 +256,17 @@ export default class Extension {
if (c > 9 || c <= 0) {
this._hideTooltips();
log(c);
return Clutter.EVENT_PROPAGATE;
return false;
}
}
const win = this._workspaces[this._active].getWindowWithTooltip(c);
let win = this._workspaces[this._active].getWindowWithTooltip(c);
this._hideTooltips();
if (win)
Main.activateWindow(win, global.get_current_time());
return Clutter.EVENT_STOP;
return true;
}
if (this._pickWorkspace) {
let c = event.get_key_symbol() - Clutter.KEY_KP_0;
@@ -274,18 +274,18 @@ export default class Extension {
c = event.get_key_symbol() - Clutter.KEY_0;
if (c > 9 || c <= 0) {
this._hideWorkspacesTooltips();
return Clutter.EVENT_PROPAGATE;
return false;
}
}
const workspace = this._workspaces[c - 1];
let workspace = this._workspaces[c - 1];
if (workspace !== undefined)
workspace.metaWorkspace.activate(global.get_current_time());
this._hideWorkspacesTooltips();
return Clutter.EVENT_STOP;
return true;
}
return Clutter.EVENT_PROPAGATE;
return false;
};
/* eslint-enable */
});

View File

@@ -5,7 +5,7 @@
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"original-author": "zaspire@rambler.ru",
"name": "Window Navigator",
"name": "windowNavigator",
"description": "Allow keyboard selection of windows and workspaces in overlay mode. <Ctrl>number selects a workspace, and <Alt>number selects a window.",
"url": "@url@"
}

View File

@@ -4,17 +4,442 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Meta from 'gi://Meta';
import St from 'gi://St';
import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
import {WorkspaceIndicator} from './workspaceIndicator.js';
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
const WORKSPACE_KEY = 'workspace-names';
const TOOLTIP_OFFSET = 6;
const TOOLTIP_ANIMATION_TIME = 150;
const MAX_THUMBNAILS = 6;
class WindowPreview extends St.Button {
static {
GObject.registerClass(this);
}
constructor(window) {
super({
style_class: 'workspace-indicator-window-preview',
});
this._delegate = this;
DND.makeDraggable(this, {restoreOnSuccess: true});
this._window = window;
this._window.connectObject(
'size-changed', () => this._checkRelayout(),
'position-changed', () => this._checkRelayout(),
'notify::minimized', this._updateVisible.bind(this),
'notify::window-type', this._updateVisible.bind(this),
this);
this._updateVisible();
global.display.connectObject('notify::focus-window',
this._onFocusChanged.bind(this), this);
this._onFocusChanged();
}
// needed for DND
get metaWindow() {
return this._window;
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_checkRelayout() {
const monitor = Main.layoutManager.findIndexForActor(this);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
if (this._window.get_frame_rect().overlap(workArea))
this.queue_relayout();
}
_updateVisible() {
this.visible = this._window.window_type !== Meta.WindowType.DESKTOP &&
this._window.showing_on_its_workspace();
}
}
class WorkspaceLayout extends Clutter.LayoutManager {
static {
GObject.registerClass(this);
}
vfunc_get_preferred_width() {
return [0, 0];
}
vfunc_get_preferred_height() {
return [0, 0];
}
vfunc_allocate(container, box) {
const monitor = Main.layoutManager.findIndexForActor(container);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
const hscale = box.get_width() / workArea.width;
const vscale = box.get_height() / workArea.height;
for (const child of container) {
const childBox = new Clutter.ActorBox();
const frameRect = child.metaWindow.get_frame_rect();
childBox.set_size(
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
childBox.set_origin(
Math.round((frameRect.x - workArea.x) * hscale),
Math.round((frameRect.y - workArea.y) * vscale));
child.allocate(childBox);
}
}
}
class WorkspaceThumbnail extends St.Button {
static {
GObject.registerClass(this);
}
constructor(index) {
super({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new WorkspaceLayout(),
clip_to_allocation: true,
x_expand: true,
y_expand: 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
this._windowPreviews = new Map();
let workspaceManager = global.workspace_manager;
this._workspace = workspaceManager.get_workspace_by_index(index);
this._workspace.connectObject(
'window-added', (ws, window) => this._addWindow(window),
'window-removed', (ws, window) => this._removeWindow(window),
this);
global.display.connectObject('restacked',
this._onRestacked.bind(this), this);
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
acceptDrop(source) {
if (!source.metaWindow)
return false;
this._moveWindow(source.metaWindow);
return true;
}
handleDragOver(source) {
if (source.metaWindow)
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);
}
on_clicked() {
let ws = global.workspace_manager.get_workspace_by_index(this._index);
if (ws)
ws.activate(global.get_current_time());
}
_syncTooltip() {
if (this.hover) {
this._tooltip.set({
text: Meta.prefs_get_workspace_name(this._index),
visible: true,
opacity: 0,
});
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.clamp(
stageX + xOffset,
monitor.x,
monitor.x + monitor.width - tipWidth);
const y = stageY + thumbHeight + TOOLTIP_OFFSET;
this._tooltip.set_position(x, y);
}
this._tooltip.ease({
opacity: this.hover ? 255 : 0,
duration: TOOLTIP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => (this._tooltip.visible = this.hover),
});
}
_onDestroy() {
this._tooltip.destroy();
}
}
class WorkspaceIndicator extends PanelMenu.Button {
static {
GObject.registerClass(this);
}
constructor() {
super(0.5, _('Workspace Indicator'));
let container = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_child(container);
let workspaceManager = global.workspace_manager;
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(),
});
container.add_child(this._statusLabel);
this._thumbnailsBox = new St.BoxLayout({
style_class: 'panel-workspace-indicator-box',
y_expand: true,
reactive: true,
});
container.add_child(this._thumbnailsBox);
this._workspacesItems = [];
this._workspaceSection = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(this._workspaceSection);
workspaceManager.connectObject(
'notify::n-workspaces', this._nWorkspacesChanged.bind(this), GObject.ConnectFlags.AFTER,
'workspace-switched', this._onWorkspaceSwitched.bind(this), GObject.ConnectFlags.AFTER,
'notify::layout-rows', this._updateThumbnailVisibility.bind(this),
this);
this.connect('scroll-event', this._onScrollEvent.bind(this));
this._thumbnailsBox.connect('scroll-event', this._onScrollEvent.bind(this));
this._createWorkspacesSection();
this._updateThumbnails();
this._updateThumbnailVisibility();
this._settings = new Gio.Settings({schema_id: WORKSPACE_SCHEMA});
this._settings.connectObject(`changed::${WORKSPACE_KEY}`,
this._updateMenuLabels.bind(this), this);
}
_onDestroy() {
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
super._onDestroy();
}
_updateThumbnailVisibility() {
const {workspaceManager} = global;
const vertical = workspaceManager.layout_rows === -1;
const useMenu =
vertical || workspaceManager.n_workspaces > MAX_THUMBNAILS;
this.reactive = useMenu;
this._statusLabel.visible = useMenu;
this._thumbnailsBox.visible = !useMenu;
// Disable offscreen-redirect when showing the workspace switcher
// so that clip-to-allocation works
Main.panel.set_offscreen_redirect(useMenu
? Clutter.OffscreenRedirect.ALWAYS
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
}
_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();
this._updateThumbnailVisibility();
}
_updateMenuOrnament() {
for (let i = 0; i < this._workspacesItems.length; i++) {
this._workspacesItems[i].setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NO_DOT);
}
}
_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;
return (workspaceIndex + 1).toString();
}
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;
this._workspaceSection.removeAll();
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._activate(actor.workspaceId);
});
this._workspacesItems[i].setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NO_DOT);
}
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_child(thumb);
}
this._updateActiveThumbnail();
}
_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 = global.workspace_manager.get_active_workspace_index() + diff;
this._activate(newIndex);
}
}
export default class WorkspaceIndicatorExtension extends Extension {
enable() {
this._indicator = new WorkspaceIndicator({
settings: this.getSettings(),
});
this._indicator = new WorkspaceIndicator();
Main.panel.addToStatusArea('workspace-indicator', this._indicator);
}

View File

@@ -7,10 +7,6 @@ extension_data += configure_file(
output: metadata_name,
configuration: metadata_conf
)
extension_data += files(
'stylesheet-dark.css',
'stylesheet-light.css',
)
extension_schemas += files('schemas/' + metadata_conf.get('gschemaname') + '.gschema.xml')
extension_data += files('stylesheet.css')
extension_sources += files('prefs.js', 'workspaceIndicator.js', 'workspacePrefs.js')
extension_sources += files('prefs.js')

View File

@@ -3,12 +3,267 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
import {ExtensionPreferences} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
import Adw from 'gi://Adw';
import Gio from 'gi://Gio';
import GLib from 'gi://GLib';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import Pango from 'gi://Pango';
import {WorkspacesPage} from './workspacePrefs.js';
import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
const N_ = e => e;
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
const WORKSPACE_KEY = 'workspace-names';
class NewItem extends GObject.Object {}
GObject.registerClass(NewItem);
class NewItemModel extends GObject.Object {
static [GObject.interfaces] = [Gio.ListModel];
static {
GObject.registerClass(this);
}
#item = new NewItem();
vfunc_get_item_type() {
return NewItem;
}
vfunc_get_n_items() {
return 1;
}
vfunc_get_item(_pos) {
return this.#item;
}
}
class WorkspacesList extends GObject.Object {
static [GObject.interfaces] = [Gio.ListModel];
static {
GObject.registerClass(this);
}
#settings = new Gio.Settings({schema_id: WORKSPACE_SCHEMA});
#names = this.#settings.get_strv(WORKSPACE_KEY);
#items = Gtk.StringList.new(this.#names);
#changedId;
constructor() {
super();
this.#changedId =
this.#settings.connect(`changed::${WORKSPACE_KEY}`, () => {
const removed = this.#names.length;
this.#names = this.#settings.get_strv(WORKSPACE_KEY);
this.#items.splice(0, removed, this.#names);
this.items_changed(0, removed, this.#names.length);
});
}
append() {
const name = _('Workspace %d').format(this.#names.length + 1);
this.#names.push(name);
this.#settings.block_signal_handler(this.#changedId);
this.#settings.set_strv(WORKSPACE_KEY, this.#names);
this.#settings.unblock_signal_handler(this.#changedId);
const pos = this.#items.get_n_items();
this.#items.append(name);
this.items_changed(pos, 0, 1);
}
remove(name) {
const pos = this.#names.indexOf(name);
if (pos < 0)
return;
this.#names.splice(pos, 1);
this.#settings.block_signal_handler(this.#changedId);
this.#settings.set_strv(WORKSPACE_KEY, this.#names);
this.#settings.unblock_signal_handler(this.#changedId);
this.#items.remove(pos);
this.items_changed(pos, 1, 0);
}
rename(oldName, newName) {
const pos = this.#names.indexOf(oldName);
if (pos < 0)
return;
this.#names.splice(pos, 1, newName);
this.#items.splice(pos, 1, [newName]);
this.#settings.block_signal_handler(this.#changedId);
this.#settings.set_strv(WORKSPACE_KEY, this.#names);
this.#settings.unblock_signal_handler(this.#changedId);
}
vfunc_get_item_type() {
return Gtk.StringObject;
}
vfunc_get_n_items() {
return this.#items.get_n_items();
}
vfunc_get_item(pos) {
return this.#items.get_item(pos);
}
}
class WorkspaceSettingsWidget extends Adw.PreferencesGroup {
static {
GObject.registerClass(this);
this.install_action('workspaces.add', null,
self => self._workspaces.append());
this.install_action('workspaces.remove', 's',
(self, name, param) => self._workspaces.remove(param.unpack()));
this.install_action('workspaces.rename', '(ss)',
(self, name, param) => self._workspaces.rename(...param.deepUnpack()));
}
constructor() {
super({
title: _('Workspace Names'),
});
this._workspaces = new WorkspacesList();
const store = new Gio.ListStore({item_type: Gio.ListModel});
const listModel = new Gtk.FlattenListModel({model: store});
store.append(this._workspaces);
store.append(new NewItemModel());
this._list = new Gtk.ListBox({
selection_mode: Gtk.SelectionMode.NONE,
css_classes: ['boxed-list'],
});
this._list.connect('row-activated', (l, row) => row.edit());
this.add(this._list);
this._list.bind_model(listModel, item => {
return item instanceof NewItem
? new NewWorkspaceRow()
: new WorkspaceRow(item.string);
});
}
}
class WorkspaceRow extends Adw.PreferencesRow {
static {
GObject.registerClass(this);
}
constructor(name) {
super({name});
const box = new Gtk.Box({
spacing: 12,
margin_top: 6,
margin_bottom: 6,
margin_start: 6,
margin_end: 6,
});
const label = new Gtk.Label({
hexpand: true,
xalign: 0,
max_width_chars: 25,
ellipsize: Pango.EllipsizeMode.END,
});
this.bind_property('name', label, 'label',
GObject.BindingFlags.SYNC_CREATE);
box.append(label);
const button = new Gtk.Button({
action_name: 'workspaces.remove',
icon_name: 'edit-delete-symbolic',
has_frame: false,
});
box.append(button);
this.bind_property_full('name',
button, 'action-target',
GObject.BindingFlags.SYNC_CREATE,
(bind, target) => [true, new GLib.Variant('s', target)],
null);
this._entry = new Gtk.Entry({
max_width_chars: 25,
});
const controller = new Gtk.ShortcutController();
controller.add_shortcut(new Gtk.Shortcut({
trigger: Gtk.ShortcutTrigger.parse_string('Escape'),
action: Gtk.CallbackAction.new(() => {
this._stopEdit();
return true;
}),
}));
this._entry.add_controller(controller);
this._stack = new Gtk.Stack();
this._stack.add_named(box, 'display');
this._stack.add_named(this._entry, 'edit');
this.child = this._stack;
this._entry.connect('activate', () => {
this.activate_action('workspaces.rename',
new GLib.Variant('(ss)', [this.name, this._entry.text]));
this.name = this._entry.text;
this._stopEdit();
});
this._entry.connect('notify::has-focus', () => {
if (this._entry.has_focus)
return;
this._stopEdit();
});
}
edit() {
this._entry.text = this.name;
this._entry.grab_focus();
this._stack.visible_child_name = 'edit';
}
_stopEdit() {
this.grab_focus();
this._stack.visible_child_name = 'display';
}
}
class NewWorkspaceRow extends Adw.PreferencesRow {
static {
GObject.registerClass(this);
}
constructor() {
super({
action_name: 'workspaces.add',
child: new Gtk.Image({
icon_name: 'list-add-symbolic',
pixel_size: 16,
margin_top: 12,
margin_bottom: 12,
margin_start: 12,
margin_end: 12,
}),
});
this.update_property(
[Gtk.AccessibleProperty.LABEL], [_('Add Workspace')]);
}
}
export default class WorkspaceIndicatorPrefs extends ExtensionPreferences {
getPreferencesWidget() {
return new WorkspacesPage(this.getSettings());
return new WorkspaceSettingsWidget();
}
}

View File

@@ -1,15 +0,0 @@
<!--
SPDX-FileCopyrightText: 2024 Florian Müllner <fmuellner@gnome.org>
SPDX-License-Identifier: GPL-2.0-or-later
-->
<schemalist gettext-domain="gnome-shell-extensions">
<schema id="org.gnome.shell.extensions.workspace-indicator"
path="/org/gnome/shell/extensions/workspace-indicator/">
<key name="embed-previews" type="b">
<default>true</default>
<summary>Show workspace previews in top bar</summary>
</key>
</schema>
</schemalist>

View File

@@ -1,130 +0,0 @@
/*
* SPDX-FileCopyrightText: 2011 Erick Pérez Castellanos <erick.red@gmail.com>
* SPDX-FileCopyrightText: 2019 Florian Müllner <fmuellner@gnome.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.workspace-indicator.previews:active {
background-color: none !important;
box-shadow: none !important;
}
.workspace-indicator.name-label {
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.17) !important;
}
.workspace-indicator.name-label:hover,
.workspace-indicator.name-label:focus {
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.28) !important;
}
.workspace-indicator.name-label:active {
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.32) !important;
}
.workspace-indicator.name-label:active:hover {
box-shadow: inset 0 0 0 100px rgba(255, 255, 255, 0.36) !important;
}
.workspace-indicator .status-label {
width: 8em;
padding: 0 8px;
}
.workspace-indicator .status-label:ltr { padding-right: 4px; }
.workspace-indicator .status-label:rtl { padding-left: 4px; }
.workspace-indicator .system-status-icon {
padding: 0 !important;
margin: 0 !important;
}
.workspace-indicator .workspaces-view.hfade {
-st-hfade-offset: 20px;
}
.workspace-indicator .workspaces-box {
spacing: 3px;
}
.workspace-indicator .workspace-box {
padding-top: 5px;
padding-bottom: 5px;
}
.workspace-indicator StButton:first-child:ltr > .workspace-box,
.workspace-indicator StButton:last-child:rtl > .workspace-box {
padding-left: 5px;
}
.workspace-indicator StButton:last-child:ltr > .workspace-box,
.workspace-indicator StButton:first-child:rtl > .workspace-box {
padding-right: 5px;
}
.workspace-indicator .workspace {
border: 1px solid transparent;
border-radius: 4px;
background-color: #3f3f3f;
}
.workspace-indicator .workspace {
width: 52px;
}
.workspace-indicator .workspace.active {
border-color: #fff;
}
.workspace-indicator-window-preview {
background-color: #bebebe;
border: 1px solid #828282;
border-radius: 1px;
}
.workspace-indicator-window-preview.active {
background-color: #d4d4d4;
}
.workspace-indicator-menu {
min-width: 17em;
}
.workspace-indicator-menu .editable-menu-item.popup-menu-item {
padding: 3px 12px;
}
.workspace-indicator-menu .editable-menu-item .icon-button {
padding: 6px;
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat {
background-color: transparent;
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:hover {
background-color: st-transparentize(white, 90%);
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:active {
background-color: st-transparentize(white, 85%);
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked {
color: -st-accent-fg-color;
background-color: -st-accent-color;
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:hover {
background-color: st-lighten(-st-accent-color, 10%);
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:active {
background-color: st-lighten(-st-accent-color, 15%);
}
.workspace-indicator-menu .editable-menu-item StLabel {
padding: 0 11px;
width: 6.5em;
}
.workspace-indicator-menu .editable-menu-item StEntry {
padding: 9px 9px;
width: 6.5em;
}

View File

@@ -1,55 +0,0 @@
/*
* SPDX-FileCopyrightText: 2013 Florian Müllner <fmuellner@gnome.org>
* SPDX-FileCopyrightText: 2015 Jakub Steiner <jimmac@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
@import url("stylesheet-dark.css");
.workspace-indicator.name-label {
box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.17) !important;
}
.workspace-indicator.name-label:hover,
.workspace-indicator.name-label:focus {
box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.28) !important;
}
.workspace-indicator.name-label:active {
box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.32) !important;
}
.workspace-indicator.name-label:active:hover {
box-shadow: inset 0 0 0 100px rgba(34, 34, 38, 0.36) !important;
}
.workspace-indicator .workspace {
background-color: #ccc;
}
.workspace-indicator .workspace.active {
border-color: #888;
}
.workspace-indicator-window-preview {
background-color: #ededed;
border: 1px solid #ccc;
}
.workspace-indicator-window-preview.active {
background-color: #f6f5f4;
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:hover {
background-color: st-transparentize(black, 90%);
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:active {
background-color: st-transparentize(black, 85%);
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:hover {
background-color: st-darken(-st-accent-color, 10%);
}
.workspace-indicator-menu .editable-menu-item .icon-button.flat:checked:active {
background-color: st-darken(-st-accent-color, 15%);
}

View File

@@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2011 Erick Pérez Castellanos <erick.red@gmail.com>
* SPDX-FileCopyrightText: 2019 Florian Müllner <fmuellner@gnome.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.panel-workspace-indicator {
padding: 0 8px;
}
.panel-workspace-indicator-box {
padding: 4px 0;
spacing: 4px;
}
.panel-workspace-indicator-box .workspace {
width: 40px;
border: 2px solid #000;
border-radius: 2px;
background-color: #595959;
}
.panel-workspace-indicator-box .workspace.active {
border-color: #fff;
}
.workspace-indicator-window-preview {
background-color: #bebebe;
border: 1px solid #828282;
}
.workspace-indicator-window-preview.active {
background-color: #d4d4d4;
}

View File

@@ -1,701 +0,0 @@
// SPDX-FileCopyrightText: 2011 Erick Pérez Castellanos <erick.red@gmail.com>
// SPDX-FileCopyrightText: 2011 Giovanni Campagna <gcampagna@src.gnome.org>
// SPDX-FileCopyrightText: 2017 Florian Müllner <fmuellner@gnome.org>
//
// SPDX-License-Identifier: GPL-2.0-or-later
import Clutter from 'gi://Clutter';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Meta from 'gi://Meta';
import Shell from 'gi://Shell';
import St from 'gi://St';
import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js';
import * as DND from 'resource:///org/gnome/shell/ui/dnd.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
const TOOLTIP_OFFSET = 6;
const TOOLTIP_ANIMATION_TIME = 150;
const SCROLL_TIME = 100;
let baseStyleClassName = '';
class WindowPreview extends St.Button {
static {
GObject.registerClass(this);
}
constructor(window) {
super({
style_class: `${baseStyleClassName}-window-preview`,
});
this._delegate = this;
DND.makeDraggable(this, {restoreOnSuccess: true});
this._window = window;
this._window.connectObject(
'size-changed', () => this._checkRelayout(),
'position-changed', () => this._checkRelayout(),
'notify::minimized', this._updateVisible.bind(this),
'notify::skip-taskbar', this._updateVisible.bind(this),
this);
this._updateVisible();
global.display.connectObject('notify::focus-window',
this._onFocusChanged.bind(this), this);
this._onFocusChanged();
}
// needed for DND
get metaWindow() {
return this._window;
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_checkRelayout() {
const monitor = Main.layoutManager.findIndexForActor(this);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
if (this._window.get_frame_rect().overlap(workArea))
this.queue_relayout();
}
_updateVisible() {
this.visible = !this._window.skip_taskbar &&
this._window.showing_on_its_workspace();
}
}
class WorkspaceLayout extends Clutter.LayoutManager {
static {
GObject.registerClass(this);
}
vfunc_get_preferred_width() {
return [0, 0];
}
vfunc_get_preferred_height() {
return [0, 0];
}
vfunc_allocate(container, box) {
const monitor = Main.layoutManager.findIndexForActor(container);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
const hscale = box.get_width() / workArea.width;
const vscale = box.get_height() / workArea.height;
for (const child of container) {
const childBox = new Clutter.ActorBox();
const frameRect = child.metaWindow.get_frame_rect();
childBox.set_size(
Math.round(Math.min(frameRect.width, workArea.width) * hscale),
Math.round(Math.min(frameRect.height, workArea.height) * vscale));
childBox.set_origin(
Math.round((frameRect.x - workArea.x) * hscale),
Math.round((frameRect.y - workArea.y) * vscale));
child.allocate(childBox);
}
}
}
class WorkspaceThumbnail extends St.Button {
static [GObject.properties] = {
'active': GObject.ParamSpec.boolean(
'active', null, null,
GObject.ParamFlags.READWRITE,
false),
};
static {
GObject.registerClass(this);
}
constructor(index) {
super();
const box = new St.BoxLayout({
style_class: 'workspace-box',
y_expand: true,
orientation: Clutter.Orientation.VERTICAL,
});
this.set_child(box);
this._preview = new St.Bin({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new WorkspaceLayout(),
clip_to_allocation: true,
x_expand: true,
y_expand: true,
}),
y_expand: true,
});
box.add_child(this._preview);
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
this._windowPreviews = new Map();
const workspaceManager = global.workspace_manager;
this._workspace = workspaceManager.get_workspace_by_index(index);
this._workspace.bind_property('active',
this, 'active',
GObject.BindingFlags.SYNC_CREATE);
this._workspace.connectObject(
'window-added', (ws, window) => this._addWindow(window),
'window-removed', (ws, window) => this._removeWindow(window),
this);
global.display.connectObject('restacked',
this._onRestacked.bind(this), this);
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
get active() {
return this._preview.has_style_class_name('active');
}
set active(active) {
if (active)
this._preview.add_style_class_name('active');
else
this._preview.remove_style_class_name('active');
this.notify('active');
}
acceptDrop(source) {
if (!source.metaWindow)
return false;
this._moveWindow(source.metaWindow);
return true;
}
handleDragOver(source) {
if (source.metaWindow)
return DND.DragMotionResult.MOVE_DROP;
else
return DND.DragMotionResult.CONTINUE;
}
_addWindow(window) {
if (this._windowPreviews.has(window))
return;
const preview = new WindowPreview(window);
preview.connect('clicked', (a, btn) => this.emit('clicked', btn));
this._windowPreviews.set(window, preview);
this._preview.child.add_child(preview);
}
_removeWindow(window) {
const preview = this._windowPreviews.get(window);
if (!preview)
return;
this._windowPreviews.delete(window);
preview.destroy();
}
_onRestacked() {
let lastPreview = null;
const windows = global.get_window_actors().map(a => a.meta_window);
for (let i = 0; i < windows.length; i++) {
const preview = this._windowPreviews.get(windows[i]);
if (!preview)
continue;
this._preview.child.set_child_above_sibling(preview, lastPreview);
lastPreview = preview;
}
}
_moveWindow(window) {
const monitorIndex = Main.layoutManager.findIndexForActor(this);
if (monitorIndex !== window.get_monitor())
window.move_to_monitor(monitorIndex);
window.change_workspace_by_index(this._index, false);
}
on_clicked() {
const ws = global.workspace_manager.get_workspace_by_index(this._index);
if (ws)
ws.activate(global.get_current_time());
}
_syncTooltip() {
if (this.hover) {
this._tooltip.set({
text: Meta.prefs_get_workspace_name(this._index),
visible: true,
opacity: 0,
});
const [stageX, stageY] = this.get_transformed_position();
const [thumbWidth, thumbHeight] = this.allocation.get_size();
const [tipWidth, tipHeight] = this._tooltip.get_size();
const xOffset = Math.floor((thumbWidth - tipWidth) / 2);
const monitor = Main.layoutManager.findMonitorForActor(this);
const x = Math.clamp(
stageX + xOffset,
monitor.x,
monitor.x + monitor.width - tipWidth);
const y = stageY - monitor.y > thumbHeight + TOOLTIP_OFFSET
? stageY - tipHeight - TOOLTIP_OFFSET // show above
: stageY + thumbHeight + TOOLTIP_OFFSET; // show below
this._tooltip.set_position(x, y);
}
this._tooltip.ease({
opacity: this.hover ? 255 : 0,
duration: TOOLTIP_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => (this._tooltip.visible = this.hover),
});
}
_onDestroy() {
this._tooltip.destroy();
}
}
class WorkspacePreviews extends Clutter.Actor {
static {
GObject.registerClass(this);
}
constructor(params) {
super({
...params,
layout_manager: new Clutter.BinLayout(),
reactive: true,
y_expand: true,
});
this.connect('scroll-event',
(a, event) => Main.wm.handleWorkspaceScroll(event));
const {workspaceManager} = global;
workspaceManager.connectObject(
'notify::n-workspaces', () => this._updateThumbnails(), GObject.ConnectFlags.AFTER,
'workspace-switched', () => this._updateScrollPosition(),
this);
this.connect('notify::mapped', () => {
if (this.mapped)
this._updateScrollPosition();
});
this._thumbnailsBox = new St.BoxLayout({
style_class: 'workspaces-box',
y_expand: true,
});
this._scrollView = new St.ScrollView({
style_class: 'workspaces-view hfade',
enable_mouse_scrolling: false,
hscrollbar_policy: St.PolicyType.EXTERNAL,
vscrollbar_policy: St.PolicyType.NEVER,
y_expand: true,
child: this._thumbnailsBox,
});
this.add_child(this._scrollView);
this._updateThumbnails();
}
_updateThumbnails() {
const {nWorkspaces} = global.workspace_manager;
this._thumbnailsBox.destroy_all_children();
for (let i = 0; i < nWorkspaces; i++)
this._thumbnailsBox.add_child(new WorkspaceThumbnail(i));
if (this.mapped)
this._updateScrollPosition();
}
_updateScrollPosition() {
const adjustment = this._scrollView.hadjustment;
const {upper, pageSize} = adjustment;
let {value} = adjustment;
const activeWorkspace =
[...this._thumbnailsBox].find(a => a.active);
if (!activeWorkspace)
return;
let offset = 0;
const hfade = this._scrollView.get_effect('fade');
if (hfade)
offset = hfade.fade_margins.left;
let {x1, x2} = activeWorkspace.get_allocation_box();
let parent = activeWorkspace.get_parent();
while (parent !== this._scrollView) {
if (!parent)
throw new Error('actor not in scroll view');
const box = parent.get_allocation_box();
x1 += box.x1;
x2 += box.x1;
parent = parent.get_parent();
}
if (x1 < value + offset)
value = Math.max(0, x1 - offset);
else if (x2 > value + pageSize - offset)
value = Math.min(upper, x2 + offset - pageSize);
else
return;
adjustment.ease(value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SCROLL_TIME,
});
}
}
class EditableMenuItem extends PopupMenu.PopupBaseMenuItem {
static [GObject.signals] = {
'edited': {},
};
static {
GObject.registerClass(this);
}
constructor() {
super({
style_class: 'editable-menu-item',
});
this.get_accessible()?.set_description(
_('Press %s to edit').format('e'));
const stack = new Shell.Stack({
x_expand: true,
x_align: Clutter.ActorAlign.START,
});
this.add_child(stack);
this.label = new St.Label({
y_align: Clutter.ActorAlign.CENTER,
});
stack.add_child(this.label);
this.label_actor = this.label;
this._entry = new St.Entry({
opacity: 0,
visible: false,
});
stack.add_child(this._entry);
this.label.bind_property('text',
this._entry, 'text',
GObject.BindingFlags.DEFAULT);
this._entry.clutter_text.connect('activate',
() => this._stopEditing());
this._editButton = new St.Button({
style_class: 'icon-button flat',
icon_name: 'document-edit-symbolic',
button_mask: St.ButtonMask.ONE,
toggle_mode: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
this.add_child(this._editButton);
this._editButton.connect('notify::checked', () => {
if (this._editButton.checked) {
this._editButton.icon_name = 'ornament-check-symbolic';
this._startEditing();
} else {
this._editButton.icon_name = 'document-edit-symbolic';
this._stopEditing();
}
});
this.connect('key-release-event', (o, event) => {
if (event.get_key_symbol() !== Clutter.KEY_e)
return Clutter.EVENT_PROPAGATE;
if (this._editButton.checked)
return Clutter.EVENT_PROPAGATE;
this._editButton.checked = true;
return Clutter.EVENT_STOP;
});
global.stage.connectObject('notify::key-focus', () => {
const {keyFocus} = global.stage;
if (!keyFocus || !this.contains(keyFocus))
this._stopEditing();
}, this);
}
_switchActor(from, to) {
to.visible = from.visible = true;
to.ease({
opacity: 255,
duration: 300,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
});
from.ease({
opacity: 0,
duration: 300,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
from.visible = false;
},
});
}
_startEditing() {
this._switchActor(this.label, this._entry);
this._entry.clutter_text.set_selection(0, -1);
this._entry.clutter_text.grab_key_focus();
}
_stopEditing() {
if (this.label.text !== this._entry.text) {
this.label.text = this._entry.text;
this.emit('edited');
}
if (this._editButton.checked)
this._editButton.checked = false;
this._switchActor(this._entry, this.label);
this.navigate_focus(this, St.DirectionType.TAB_FORWARD, false);
}
}
class WorkspacesMenu extends PopupMenu.PopupMenu {
constructor(sourceActor) {
super(sourceActor, 0.5, St.Side.TOP);
this.actor.add_style_class_name(`${baseStyleClassName}-menu`);
this._workspacesSection = new PopupMenu.PopupMenuSection();
this.addMenuItem(this._workspacesSection);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.addAction(_('Settings'), () => {
const extension = Extension.lookupByURL(import.meta.url);
extension.openPreferences();
});
this._desktopSettings =
new Gio.Settings({schema_id: 'org.gnome.desktop.wm.preferences'});
this._desktopSettings.connectObject('changed::workspace-names', () => {
this._updateWorkspaceLabels();
this.emit('active-name-changed');
}, this);
const {workspaceManager} = global;
workspaceManager.connectObject(
'notify::n-workspaces', () => this._updateWorkspaceItems(),
'workspace-switched', () => this._updateActiveIndicator(),
this.actor);
this._updateWorkspaceItems();
}
get activeName() {
const {workspaceManager} = global;
const active = workspaceManager.get_active_workspace_index();
return Meta.prefs_get_workspace_name(active);
}
_updateWorkspaceItems() {
const {workspaceManager} = global;
const {nWorkspaces} = workspaceManager;
const section = this._workspacesSection.actor;
while (section.get_n_children() < nWorkspaces) {
const item = new EditableMenuItem();
item.connect('activate', (o, event) => {
const index = [...section].indexOf(item);
const workspace = workspaceManager.get_workspace_by_index(index);
workspace?.activate(event.get_time());
});
item.connect('edited', () => {
const nLabels = section.get_n_children();
const oldNames = this._desktopSettings.get_strv('workspace-names');
const newNames = [...section].map(c => c.label.text);
this._desktopSettings.set_strv('workspace-names',
[...newNames, ...oldNames.slice(nLabels)]);
});
this._workspacesSection.addMenuItem(item);
}
[...section].splice(nWorkspaces).forEach(item => item.destroy());
this._updateWorkspaceLabels();
this._updateActiveIndicator();
}
_updateWorkspaceLabels() {
const items = [...this._workspacesSection.actor];
items.forEach(
(item, i) => (item.label.text = Meta.prefs_get_workspace_name(i)));
}
_updateActiveIndicator() {
const {workspaceManager} = global;
const active = workspaceManager.get_active_workspace_index();
const items = [...this._workspacesSection.actor];
items.forEach((item, i) => {
item.setOrnament(i === active
? PopupMenu.Ornament.CHECK
: PopupMenu.Ornament.NONE);
});
this.emit('active-name-changed');
}
}
export class WorkspaceIndicator extends PanelMenu.Button {
static {
GObject.registerClass(this);
}
constructor(params = {}) {
super(0.5, _('Workspace Indicator'), true);
const {
baseStyleClass = 'workspace-indicator',
settings,
} = params;
this._settings = settings;
baseStyleClassName = baseStyleClass;
this.add_style_class_name(baseStyleClassName);
this.setMenu(new WorkspacesMenu(this));
const container = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_child(container);
this._statusBox = new St.BoxLayout();
container.add_child(this._statusBox);
this._statusLabel = new St.Label({
style_class: 'status-label',
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
text: this.menu.activeName,
});
this._statusBox.add_child(this._statusLabel);
this._statusBox.add_child(new St.Icon({
icon_name: 'pan-down-symbolic',
style_class: 'system-status-icon',
}));
this.menu.connect('active-name-changed',
() => this._statusLabel.set_text(this.menu.activeName));
this._thumbnails = new WorkspacePreviews();
container.add_child(this._thumbnails);
this._thumbnails.connect('button-press-event', (a, event) => {
if (event.get_button() !== Clutter.BUTTON_SECONDARY)
return Clutter.EVENT_PROPAGATE;
this.menu.toggle();
return Clutter.EVENT_STOP;
});
this.connect('scroll-event',
(a, event) => Main.wm.handleWorkspaceScroll(event));
this._inTopBar = false;
this.connect('notify::realized', () => {
if (!this.realized)
return;
this._inTopBar = Main.panel.contains(this);
this._updateTopBarRedirect();
});
this._settings.connect('changed::embed-previews',
() => this._updateThumbnailVisibility());
this._updateThumbnailVisibility();
}
_onDestroy() {
if (this._inTopBar)
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._inTopBar = false;
super._onDestroy();
}
_updateThumbnailVisibility() {
const usePreviews = this._settings.get_boolean('embed-previews');
this.reactive = !usePreviews;
this._thumbnails.visible = usePreviews;
this._statusBox.visible = !usePreviews;
if (usePreviews) {
this.add_style_class_name('previews');
this.remove_style_class_name('name-label');
} else {
this.remove_style_class_name('previews');
this.add_style_class_name('name-label');
}
this._updateTopBarRedirect();
}
_updateTopBarRedirect() {
if (!this._inTopBar)
return;
// Disable offscreen-redirect when showing the workspace switcher
// so that clip-to-allocation works
Main.panel.set_offscreen_redirect(this._thumbnails.visible
? Clutter.OffscreenRedirect.ALWAYS
: Clutter.OffscreenRedirect.AUTOMATIC_FOR_OPACITY);
}
}

View File

@@ -1,135 +0,0 @@
// SPDX-FileCopyrightText: 2012 Giovanni Campagna <gcampagna@src.gnome.org>
// SPDX-FileCopyrightText: 2014 Florian Müllner <fmuellner@gnome.org>
//
// SPDX-License-Identifier: GPL-2.0-or-later
import Adw from 'gi://Adw';
import Gio from 'gi://Gio';
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import {gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
class GeneralGroup extends Adw.PreferencesGroup {
static {
GObject.registerClass(this);
}
constructor(settings) {
super({
title: _('Indicator'),
});
const previewCheck = new Gtk.CheckButton();
const previewRow = new Adw.ActionRow({
title: _('Previews'),
activatable_widget: previewCheck,
});
previewRow.add_prefix(previewCheck);
this.add(previewRow);
const nameCheck = new Gtk.CheckButton({
group: previewCheck,
});
const nameRow = new Adw.ActionRow({
title: _('Workspace Name'),
activatable_widget: nameCheck,
});
nameRow.add_prefix(nameCheck);
this.add(nameRow);
if (settings.get_boolean('embed-previews'))
previewCheck.active = true;
else
nameCheck.active = true;
settings.bind('embed-previews',
previewCheck, 'active',
Gio.SettingsBindFlags.DEFAULT);
}
}
class BehaviorGroup extends Adw.PreferencesGroup {
static {
GObject.registerClass(this);
}
constructor() {
super({
title: _('Behavior'),
});
const dynamicCheck = new Gtk.CheckButton();
const dynamicRow = new Adw.ActionRow({
title: _('Dynamic'),
subtitle: _('Automatically removes empty workspaces.'),
activatable_widget: dynamicCheck,
});
dynamicRow.add_prefix(dynamicCheck);
this.add(dynamicRow);
const fixedCheck = new Gtk.CheckButton({
group: dynamicCheck,
});
const fixedRow = new Adw.ActionRow({
title: _('Fixed Number'),
subtitle: _('Specify a number of permanent workspaces.'),
activatable_widget: fixedCheck,
});
fixedRow.add_prefix(fixedCheck);
this.add(fixedRow);
const adjustment = new Gtk.Adjustment({
lower: 1,
step_increment: 1,
value: 4,
upper: 36, // hard limit in mutter
});
const numRow = new Adw.SpinRow({
title: _('Number of Workspaces'),
adjustment,
});
this.add(numRow);
const mutterSettings = new Gio.Settings({
schema_id: 'org.gnome.mutter',
});
if (mutterSettings.get_boolean('dynamic-workspaces'))
dynamicCheck.active = true;
else
fixedCheck.active = true;
mutterSettings.bind('dynamic-workspaces',
dynamicCheck, 'active',
Gio.SettingsBindFlags.DEFAULT);
const desktopSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.wm.preferences',
});
desktopSettings.bind('num-workspaces',
numRow, 'value',
Gio.SettingsBindFlags.DEFAULT);
fixedCheck.bind_property('active',
numRow, 'sensitive',
GObject.BindingFlags.SYNC_CREATE);
}
}
export class WorkspacesPage extends Adw.PreferencesPage {
static {
GObject.registerClass(this);
}
constructor(settings) {
super({
title: _('Workspaces'),
icon_name: 'view-grid-symbolic',
});
this.add(new GeneralGroup(settings));
this.add(new BehaviorGroup());
}
}

View File

@@ -32,4 +32,10 @@ and will be picked automatically at next login.
<gnome:userid>fmuellner</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Marge Bot</foaf:name>
<gnome:userid>marge-bot</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

273
lint/eslintrc-gjs.yml Normal file
View File

@@ -0,0 +1,273 @@
---
# SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
# SPDX-FileCopyrightText: 2018 Claudio André <claudioandre.br@gmail.com>
env:
es2021: true
extends: 'eslint:recommended'
plugins:
- jsdoc
rules:
array-bracket-newline:
- error
- consistent
array-bracket-spacing:
- error
- never
array-callback-return: error
arrow-parens:
- error
- as-needed
arrow-spacing: error
block-scoped-var: error
block-spacing: error
brace-style: error
# Waiting for this to have matured a bit in eslint
# camelcase:
# - error
# - properties: never
# allow: [^vfunc_, ^on_, _instance_init]
comma-dangle:
- error
- arrays: always-multiline
objects: always-multiline
functions: never
comma-spacing:
- error
- before: false
after: true
comma-style:
- error
- last
computed-property-spacing: error
curly:
- error
- multi-or-nest
- consistent
dot-location:
- error
- property
eol-last: error
eqeqeq: error
func-call-spacing: error
func-name-matching: error
func-style:
- error
- declaration
- allowArrowFunctions: true
indent:
- error
- 4
- ignoredNodes:
# Allow not indenting the body of GObject.registerClass, since in the
# future it's intended to be a decorator
- 'CallExpression[callee.object.name=GObject][callee.property.name=registerClass] > ClassExpression:first-child'
# Allow dedenting chained member expressions
MemberExpression: 'off'
jsdoc/check-alignment: error
jsdoc/check-param-names: error
jsdoc/check-tag-names: error
jsdoc/check-types: error
jsdoc/implements-on-classes: error
jsdoc/tag-lines:
- error
- any
- startLines: 1
jsdoc/require-jsdoc: error
jsdoc/require-param: error
jsdoc/require-param-description: error
jsdoc/require-param-name: error
jsdoc/require-param-type: error
key-spacing:
- error
- beforeColon: false
afterColon: true
keyword-spacing:
- error
- before: true
after: true
linebreak-style:
- error
- unix
lines-between-class-members:
- error
- always
- exceptAfterSingleLine: true
max-nested-callbacks: error
max-statements-per-line: error
new-parens: error
no-array-constructor: error
no-await-in-loop: error
no-caller: error
no-constant-condition:
- error
- checkLoops: false
no-div-regex: error
no-empty:
- error
- allowEmptyCatch: true
no-extra-bind: error
no-extra-parens:
- error
- all
- conditionalAssign: false
nestedBinaryExpressions: false
returnAssign: false
no-implicit-coercion:
- error
- allow:
- '!!'
no-invalid-this: error
no-iterator: error
no-label-var: error
no-lonely-if: error
no-loop-func: error
no-nested-ternary: error
no-new-object: error
no-new-wrappers: error
no-octal-escape: error
no-proto: error
no-prototype-builtins: 'off'
no-restricted-globals: [error, window]
no-restricted-properties:
- error
- object: imports
property: format
message: Use template strings
- object: pkg
property: initFormat
message: Use template strings
- object: Lang
property: copyProperties
message: Use Object.assign()
- object: Lang
property: bind
message: Use arrow notation or Function.prototype.bind()
- object: Lang
property: Class
message: Use ES6 classes
no-restricted-syntax:
- error
- selector: >-
MethodDefinition[key.name="_init"] >
FunctionExpression[params.length=1] >
BlockStatement[body.length=1]
CallExpression[arguments.length=1][callee.object.type="Super"][callee.property.name="_init"] >
Identifier:first-child
message: _init() that only calls super._init() is unnecessary
- selector: >-
MethodDefinition[key.name="_init"] >
FunctionExpression[params.length=0] >
BlockStatement[body.length=1]
CallExpression[arguments.length=0][callee.object.type="Super"][callee.property.name="_init"]
message: _init() that only calls super._init() is unnecessary
- selector: BinaryExpression[operator="instanceof"][right.name="Array"]
message: Use Array.isArray()
no-return-assign: error
no-return-await: error
no-self-compare: error
no-shadow: error
no-shadow-restricted-names: error
no-spaced-func: error
no-tabs: error
no-template-curly-in-string: error
no-throw-literal: error
no-trailing-spaces: error
no-undef-init: error
no-unneeded-ternary: error
no-unused-expressions: error
no-unused-vars:
- error
# Vars use a suffix _ instead of a prefix because of file-scope private vars
- varsIgnorePattern: (^unused|_$)
argsIgnorePattern: ^(unused|_)
no-useless-call: error
no-useless-computed-key: error
no-useless-concat: error
no-useless-constructor: error
no-useless-rename: error
no-useless-return: error
no-whitespace-before-property: error
no-with: error
nonblock-statement-body-position:
- error
- below
object-curly-newline:
- error
- consistent: true
multiline: true
object-curly-spacing: error
object-shorthand: error
operator-assignment: error
operator-linebreak: error
padded-blocks:
- error
- never
# These may be a bit controversial, we can try them out and enable them later
# prefer-const: error
# prefer-destructuring: error
prefer-numeric-literals: error
prefer-promise-reject-errors: error
prefer-rest-params: error
prefer-spread: error
prefer-template: error
quotes:
- error
- single
- avoidEscape: true
require-await: error
rest-spread-spacing: error
semi:
- error
- always
semi-spacing:
- error
- before: false
after: true
semi-style: error
space-before-blocks: error
space-before-function-paren:
- error
- named: never
# for `function ()` and `async () =>`, preserve space around keywords
anonymous: always
asyncArrow: always
space-in-parens: error
space-infix-ops:
- error
- int32Hint: false
space-unary-ops: error
spaced-comment: error
switch-colon-spacing: error
symbol-description: error
template-curly-spacing: error
template-tag-spacing: error
unicode-bom: error
wrap-iife:
- error
- inside
yield-star-spacing: error
yoda: error
settings:
jsdoc:
mode: typescript
globals:
ARGV: readonly
Debugger: readonly
GIRepositoryGType: readonly
globalThis: readonly
imports: readonly
Intl: readonly
log: readonly
logError: readonly
print: readonly
printerr: readonly
window: readonly
TextEncoder: readonly
TextDecoder: readonly
console: readonly
setTimeout: readonly
setInterval: readonly
clearTimeout: readonly
clearInterval: readonly
parserOptions:
ecmaVersion: 2022

24
lint/eslintrc-shell.yml Normal file
View File

@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2019 Florian Müllner <fmuellner@gnome.org>
#
# SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
rules:
camelcase:
- error
- properties: never
allow: [^vfunc_, ^on_]
consistent-return: error
eqeqeq:
- error
- smart
prefer-arrow-callback: error
jsdoc/require-param-description: off
jsdoc/require-jsdoc:
- error
- exemptEmptyFunctions: true
publicOnly:
esm: true
globals:
global: readonly
parserOptions:
sourceType: module

View File

@@ -4,8 +4,8 @@
project(
'gnome-shell-extensions',
version: '50.alpha',
meson_version: '>= 1.1.0',
version: '46.3',
meson_version: '>= 0.58.0',
license: 'GPL-2.0-or-later',
)
@@ -23,15 +23,9 @@ modedir = join_paths(shelldir, 'modes')
schemadir = join_paths(datadir, 'glib-2.0', 'schemas')
sessiondir = join_paths(datadir, 'gnome-session', 'sessions')
xsessiondir = join_paths(datadir, 'xsessions')
wlsessiondir = join_paths(datadir, 'wayland-sessions')
systemd_dep = dependency('systemd', required: false)
systemd_userunitdir = systemd_dep.get_variable(
pkgconfig: 'systemduserunitdir',
pkgconfig_define: ['prefix', get_option('prefix')],
default_value: get_option('prefix') / 'lib' / 'systemd' / 'user',
)
ver_arr = meson.project_version().split('.')
shell_version = ver_arr[0]
@@ -49,7 +43,6 @@ default_extensions += [
'drive-menu',
'light-style',
'screenshot-window-sizer',
'status-icons',
'system-monitor',
'windowsNavigator',
'workspace-indicator',
@@ -92,6 +85,10 @@ endforeach
if classic_mode_enabled
subdir('data')
meson.add_install_script(
'meson/session-post-install.py',
join_paths(get_option('prefix'), datadir),
)
endif
subdir('extensions')
@@ -99,7 +96,7 @@ subdir('po')
gnome.post_install(glib_compile_schemas: true)
meson.add_dist_script('build-aux/check-version.py', meson.project_version(), 'NEWS')
meson.add_dist_script('meson/check-version.py', meson.project_version(), 'NEWS')
summary_options = {
'extensions': enabled_extensions,

24
meson/session-post-install.py Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2021 Neal Gompa <ngompa@fedoraproject.org>
#
# SPDX-License-Identifier: GPL-2.0-or-later
import os
import shutil
import sys
if os.environ.get('DESTDIR'):
install_root = os.environ.get('DESTDIR') + os.path.abspath(sys.argv[1])
else:
install_root = sys.argv[1]
# FIXME: Meson is unable to copy a generated target file:
# https://groups.google.com/forum/#!topic/mesonbuild/3iIoYPrN4P0
dst_dir = os.path.join(install_root, 'wayland-sessions')
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
src = os.path.join(install_root, 'xsessions', 'gnome-classic.desktop')
dst = os.path.join(dst_dir, 'gnome-classic.desktop')
shutil.copyfile(src, dst)

View File

@@ -29,7 +29,6 @@ he
hi
hr
hu
ia
id
is
it

View File

@@ -1,4 +1,6 @@
data/gnome-classic.desktop.in
data/gnome-classic-wayland.desktop.in
data/gnome-classic-xorg.desktop.in
extensions/apps-menu/extension.js
extensions/auto-move-windows/extension.js
extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml
@@ -15,7 +17,7 @@ extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml
extensions/window-list/extension.js
extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml
extensions/window-list/prefs.js
extensions/window-list/workspaceIndicator.js
extensions/windowsNavigator/extension.js
extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml
extensions/workspace-indicator/workspaceIndicator.js
extensions/workspace-indicator/workspacePrefs.js
extensions/workspace-indicator/extension.js
extensions/workspace-indicator/prefs.js

192
po/be.po
View File

@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: gnome-shell-extensions master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
"issues\n"
"POT-Creation-Date: 2025-06-18 23:32+0000\n"
"PO-Revision-Date: 2025-06-21 15:51+0300\n"
"POT-Creation-Date: 2024-02-06 18:43+0000\n"
"PO-Revision-Date: 2024-02-15 08:27+0300\n"
"Last-Translator: Yuras Shumovich <shumovichy@gmail.com>\n"
"Language-Team: Belarusian <i18n-bel-gnome@googlegroups.com>\n"
"Language: be\n"
@@ -18,7 +18,7 @@ msgstr ""
"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 3.5\n"
"X-Generator: Poedit 3.4.2\n"
#: data/gnome-classic.desktop.in:3
msgid "GNOME Classic"
@@ -37,11 +37,11 @@ msgstr "Класічны GNOME на Wayland"
msgid "GNOME Classic on Xorg"
msgstr "Класічны GNOME на Xorg"
#: extensions/apps-menu/extension.js:118
#: extensions/apps-menu/extension.js:126
msgid "Favorites"
msgstr "Абраныя"
#: extensions/apps-menu/extension.js:392
#: extensions/apps-menu/extension.js:397
msgid "Apps"
msgstr "Праграмы"
@@ -57,17 +57,17 @@ msgstr ""
"Спіс радкоў, кожны з якіх змяшчае ідэнтыфікатар праграмы (імя файла *."
"desktop), затым двукроп'е і нумар працоўнай прасторы"
#: extensions/auto-move-windows/prefs.js:156
#: extensions/auto-move-windows/prefs.js:159
msgid "Workspace Rules"
msgstr "Правілы для працоўнай прасторы"
#: extensions/auto-move-windows/prefs.js:311
#: extensions/auto-move-windows/prefs.js:314
msgid "Add Rule"
msgstr "Дадаць правіла"
#. TRANSLATORS: %s is the filesystem name
#: extensions/drive-menu/extension.js:123
#: extensions/places-menu/placeDisplay.js:186
#: extensions/places-menu/placeDisplay.js:218
#, javascript-format
msgid "Ejecting drive “%s” failed:"
msgstr "Не ўдалося выняць дыск «%s»:"
@@ -91,7 +91,7 @@ msgid ""
"This setting applies only with the natural placement strategy."
msgstr ""
"Спрабаваць выкарыстаць большую плошчу экрана для размяшчэння мініяцюр праз "
"змяненне суадносін бакоў экрана, ушчыльняючы іх, каб зменшыць памеры "
"змяненне суадносін бакоў экрана, ўшчыльняючы іх, каб зменшыць памеры "
"абмежавальнай рамкі. Гэты параметр ужываецца толькі з натуральным "
"размяшчэннем мініяцюр."
@@ -105,44 +105,37 @@ msgid ""
"shell default of placing it at the bottom. Changing this setting requires "
"restarting the shell to have any effect."
msgstr ""
"Калі выбрана, подпіс акна будзе над мініяцюрай, а не пад ёй (як "
"Калі выбрана, подпіс акна будзе над мініяцюрай, а не пад ей (як "
"перадвызначана). Каб змена налады ўступіла ў сілу, трэба перазапусціць "
"абалонку."
#: extensions/places-menu/extension.js:75
#: extensions/places-menu/extension.js:78
#: extensions/places-menu/extension.js:91
#: extensions/places-menu/extension.js:94
msgid "Places"
msgstr "Месцы"
#: extensions/places-menu/placeDisplay.js:52
#: extensions/places-menu/placeDisplay.js:60
#, javascript-format
msgid "Failed to launch “%s”"
msgstr "Не ўдалося запусціць «%s»"
#: extensions/places-menu/placeDisplay.js:67
#: extensions/places-menu/placeDisplay.js:75
#, javascript-format
msgid "Failed to mount volume for “%s”"
msgstr "Не ўдалося прымацаваць том для «%s»."
#: extensions/places-menu/placeDisplay.js:315
#: extensions/places-menu/placeDisplay.js:135
#: extensions/places-menu/placeDisplay.js:158
msgid "Computer"
msgstr "Камп'ютар"
#: extensions/places-menu/placeDisplay.js:333
msgid "Home"
msgstr "Хатняя папка"
#: extensions/places-menu/placeDisplay.js:321
msgid "Recent"
msgstr "Нядаўнія"
#: extensions/places-menu/placeDisplay.js:327
msgid "Starred"
msgstr "Абраныя"
#: extensions/places-menu/placeDisplay.js:347
msgid "Network"
msgstr "Сетка"
#: extensions/places-menu/placeDisplay.js:354
msgid "Trash"
msgstr "Сметніца"
#: extensions/places-menu/placeDisplay.js:378
msgid "Browse Network"
msgstr "Агляд сеткі"
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:14
msgid "Cycle Screenshot Sizes"
@@ -164,49 +157,49 @@ msgstr "Статыстыка выкарыстання памяці"
msgid "Swap stats"
msgstr "Статыстыка выкарыстання своп"
#: extensions/system-monitor/extension.js:336
#: extensions/system-monitor/extension.js:327
msgid "Upload stats"
msgstr "Статыстыка адпраўлення даных"
#: extensions/system-monitor/extension.js:350
#: extensions/system-monitor/extension.js:341
msgid "Download stats"
msgstr "Статыстыка атрымання даных"
#: extensions/system-monitor/extension.js:364
#: extensions/system-monitor/extension.js:355
msgid "System stats"
msgstr "Статыстыка сістэмы"
#: extensions/system-monitor/extension.js:412
#: extensions/system-monitor/extension.js:403
msgid "Show"
msgstr "Паказваць"
#: extensions/system-monitor/extension.js:414
#: extensions/system-monitor/extension.js:405
msgid "CPU"
msgstr "Працэсар"
#: extensions/system-monitor/extension.js:416
#: extensions/system-monitor/extension.js:407
msgid "Memory"
msgstr "Памяць"
#: extensions/system-monitor/extension.js:418
#: extensions/system-monitor/extension.js:409
msgid "Swap"
msgstr "Своп"
#: extensions/system-monitor/extension.js:420
#: extensions/system-monitor/extension.js:411
msgid "Upload"
msgstr "Атрыманне"
#: extensions/system-monitor/extension.js:422
#: extensions/system-monitor/extension.js:413
msgid "Download"
msgstr "Адпраўленне"
#: extensions/system-monitor/extension.js:427
#: extensions/system-monitor/extension.js:418
msgid "Open System Monitor"
msgstr "Адкрыць сістэмны манітор"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:12
msgid "Show CPU usage"
msgstr "Паказваць выкарыстанне працэсара"
msgstr "Паказваць выкарыстанне працэссара"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:16
msgid "Show memory usage"
@@ -232,47 +225,47 @@ msgstr "Назва тэмы"
msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell"
msgstr "Назва тэмы, што загрузіцца з ~/.themes/name/gnome-shell"
#: extensions/window-list/extension.js:98
#: extensions/window-list/extension.js:71
msgid "Close"
msgstr "Закрыць"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:98
msgid "Unminimize"
msgstr "Скасаваць згортванне"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:98
msgid "Minimize"
msgstr "Згарнуць"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:105
msgid "Unmaximize"
msgstr "Скасаваць разгортванне"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:105
msgid "Maximize"
msgstr "Разгарнуць"
#: extensions/window-list/extension.js:720
#: extensions/window-list/extension.js:470
msgid "Minimize all"
msgstr "Згарнуць усе"
#: extensions/window-list/extension.js:726
#: extensions/window-list/extension.js:476
msgid "Unminimize all"
msgstr "Скасаваць згортванне для ўсіх"
#: extensions/window-list/extension.js:732
#: extensions/window-list/extension.js:482
msgid "Maximize all"
msgstr "Разгарнуць усе"
#: extensions/window-list/extension.js:740
#: extensions/window-list/extension.js:490
msgid "Unmaximize all"
msgstr "Скасаваць разгортванне для ўсіх"
#: extensions/window-list/extension.js:748
#: extensions/window-list/extension.js:498
msgid "Close all"
msgstr "Закрыць усе"
#: extensions/window-list/extension.js:1000 extensions/window-list/prefs.js:23
#: extensions/window-list/extension.js:772
msgid "Window List"
msgstr "Спіс вокнаў"
@@ -289,7 +282,7 @@ msgstr ""
"значэнні: «never» (ніколі), «auto» (аўтаматычна), «always» (заўсёды)."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:26
#: extensions/window-list/prefs.js:74
#: extensions/window-list/prefs.js:79
msgid "Show windows from all workspaces"
msgstr "Паказваць вокны з усіх працоўных прастор"
@@ -308,102 +301,43 @@ msgid ""
msgstr ""
"Паказваць спіс вокнаў на ўсіх падлучаных маніторах ці толькі на асноўным."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:41
msgid "Show workspace previews in window list"
msgstr "Паказваць папярэдні прагляд працоўных прастор у спісе акон"
#: extensions/window-list/prefs.js:41
#: extensions/window-list/prefs.js:35
msgid "Window Grouping"
msgstr "Групаванне вокнаў"
#: extensions/window-list/prefs.js:46
#: extensions/window-list/prefs.js:40
msgid "Never group windows"
msgstr "Ніколі не групаваць вокны"
#: extensions/window-list/prefs.js:47
#: extensions/window-list/prefs.js:41
msgid "Group windows when space is limited"
msgstr "Групаваць вокны калі не хапае месца"
#: extensions/window-list/prefs.js:48
#: extensions/window-list/prefs.js:42
msgid "Always group windows"
msgstr "Заўсёды групаваць вокны"
#: extensions/window-list/prefs.js:68
#: extensions/window-list/prefs.js:66
msgid "Show on all monitors"
msgstr "Паказваць на ўсіх маніторах"
#: extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml:12
msgid "Show workspace previews in top bar"
msgstr "Паказваць папярэдні прагляд працоўных прастор у верхняй панэлі"
#: extensions/workspace-indicator/workspaceIndicator.js:404
#, javascript-format
msgid "Press %s to edit"
msgstr "Націсніце %s, каб змяніць"
#: extensions/workspace-indicator/workspaceIndicator.js:512
msgid "Settings"
msgstr "Налады"
#: extensions/workspace-indicator/workspaceIndicator.js:592
#: extensions/window-list/workspaceIndicator.js:253
#: extensions/workspace-indicator/extension.js:259
msgid "Workspace Indicator"
msgstr "Індыкатар працоўнай прасторы"
#: extensions/workspace-indicator/workspacePrefs.js:20
msgid "Indicator"
msgstr "Індыкатар"
#: extensions/workspace-indicator/workspacePrefs.js:25
msgid "Previews"
msgstr "Перадпрагляд"
#: extensions/workspace-indicator/workspacePrefs.js:35
msgid "Workspace Name"
msgstr "Назва працоўнай прасторы"
#: extensions/workspace-indicator/workspacePrefs.js:59
msgid "Behavior"
msgstr "Паводзіны"
#: extensions/workspace-indicator/workspacePrefs.js:64
msgid "Dynamic"
msgstr "Дынамічная"
#: extensions/workspace-indicator/workspacePrefs.js:65
msgid "Automatically removes empty workspaces."
msgstr "Пустыя працоўныя прасторы выдаляюцца аўтаматычна."
#: extensions/workspace-indicator/workspacePrefs.js:75
msgid "Fixed Number"
msgstr "Фіксаваная колькасць'"
#: extensions/workspace-indicator/workspacePrefs.js:76
msgid "Specify a number of permanent workspaces."
msgstr "Вызначыце колькасць пастаянных працоўных прастор."
#: extensions/workspace-indicator/workspacePrefs.js:89
msgid "Number of Workspaces"
msgstr "Колькасць працоўных прастор"
#: extensions/workspace-indicator/workspacePrefs.js:128
msgid "Workspaces"
msgstr "Працоўныя прасторы"
#: extensions/workspace-indicator/prefs.js:69
#, javascript-format
#~ msgid "Workspace %d"
#~ msgstr "Працоўная прастора %d"
msgid "Workspace %d"
msgstr "Працоўная прастора %d"
#~ msgid "Add Workspace"
#~ msgstr "Дадаць працоўную прастору"
#: extensions/workspace-indicator/prefs.js:136
msgid "Workspace Names"
msgstr "Назвы працоўных прастор"
#~ msgid "Remove"
#~ msgstr "Выдаліць"
#~ msgid "Computer"
#~ msgstr "Камп'ютар"
#~ msgid "Show workspace previews"
#~ msgstr "Паказваць папярэдні прагляд працоўных прастор"
#: extensions/workspace-indicator/prefs.js:262
msgid "Add Workspace"
msgstr "Дадаць працоўную прастору"
#~ msgid "Applications"
#~ msgstr "Праграмы"
@@ -469,7 +403,7 @@ msgstr "Працоўныя прасторы"
#~ "If not empty, it contains the text that will be shown when clicking on "
#~ "the panel."
#~ msgstr ""
#~ "Калі не пуста, змяшчае тэкст, які будзе паказвацца пры націсканні на "
#~ "Калі не пуста, ўтрымлівае тэкст, які будзе паказвацца пры націсканні на "
#~ "панэль."
#~ msgid "Message"

263
po/bg.po
View File

@@ -7,87 +7,86 @@
# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2021, 2022.
# Lyubomir Vasilev <lyubomirv@abv.bg>, 2017.
# twlvnn kraftwerk <kraft_werk@tutanota.com>, 2024.
# @pacu23, 2025
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell-extensions main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
"issues\n"
"POT-Creation-Date: 2025-11-05 13:44+0000\n"
"PO-Revision-Date: 2026-01-01 18:41+0200\n"
"Last-Translator: @pacu23\n"
"POT-Creation-Date: 2024-08-12 20:30+0000\n"
"PO-Revision-Date: 2024-09-02 10:45+0200\n"
"Last-Translator: twlvnn kraftwerk <kraft_werk@tutanota.com>\n"
"Language-Team: Bulgarian <dict@ludost.net>\n"
"Language: bg\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 3.8\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"X-Generator: Gtranslator 46.1\n"
#: data/gnome-classic.desktop.in:2
#: data/gnome-classic.desktop.in:3
msgid "GNOME Classic"
msgstr "Класически GNOME"
#: data/gnome-classic.desktop.in:3 data/gnome-classic-wayland.desktop.in:3
#: data/gnome-classic-xorg.desktop.in:3
#: data/gnome-classic.desktop.in:4 data/gnome-classic-wayland.desktop.in:4
#: data/gnome-classic-xorg.desktop.in:4
msgid "This session logs you into GNOME Classic"
msgstr "Тази сесия влизa в Класически GNOME"
msgstr "Работната среда изглежда като класическия GNOME (2.x)"
#: data/gnome-classic-wayland.desktop.in:2
#: data/gnome-classic-wayland.desktop.in:3
msgid "GNOME Classic on Wayland"
msgstr "Класически GNOME в Wayland"
#: data/gnome-classic-xorg.desktop.in:2
#: data/gnome-classic-xorg.desktop.in:3
msgid "GNOME Classic on Xorg"
msgstr "Класически GNOME в Xorg"
#: extensions/apps-menu/extension.js:118
#: extensions/apps-menu/extension.js:126
msgid "Favorites"
msgstr "Любими"
#: extensions/apps-menu/extension.js:392
#: extensions/apps-menu/extension.js:400
msgid "Apps"
msgstr "Програми"
#: extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml:12
msgid "Application and workspace list"
msgstr "Списък с програмите и работните пространства"
msgstr "Списък с програмите и работните плотове"
#: extensions/auto-move-windows/org.gnome.shell.extensions.auto-move-windows.gschema.xml:13
msgid ""
"A list of strings, each containing an application id (desktop file name), "
"followed by a colon and the workspace number"
msgstr ""
"Списък от низове, всеки съдържащ идентификатор на програма (име на desktop "
"файла), последван от двоеточие и номер на работното пространство"
"Списък от низове. Всеки съдържа идентификатор на програма (име на файл „."
"desktop“), следван от знака „:“ и номер на работен плот"
#: extensions/auto-move-windows/prefs.js:157
#: extensions/auto-move-windows/prefs.js:159
msgid "Workspace Rules"
msgstr "Правила за работните пространства"
msgstr "Правила за работните плотове"
#: extensions/auto-move-windows/prefs.js:312
#: extensions/auto-move-windows/prefs.js:314
msgid "Add Rule"
msgstr "Добавяне на правило"
#. TRANSLATORS: %s is the filesystem name
#: extensions/drive-menu/extension.js:123
#: extensions/places-menu/placeDisplay.js:186
#: extensions/places-menu/placeDisplay.js:218
#, javascript-format
msgid "Ejecting drive “%s” failed:"
msgstr "Неуспешно изваждане на устройството „%s\":"
msgstr "Неуспешно изваждане на устройство „%s:"
#: extensions/drive-menu/extension.js:142
msgid "Removable devices"
msgstr "Преносими устройства"
msgstr "Преносими медии"
#: extensions/drive-menu/extension.js:164
msgid "Open Files"
msgstr "Отвори „Файлове"
msgstr "Отваряне на файлове"
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:11
msgid "Use more screen for windows"
msgstr "Повече пространство на екрана за прозорците"
msgstr "Повече пространство за прозорците"
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:12
msgid ""
@@ -95,10 +94,10 @@ msgid ""
"aspect ratio, and consolidating them further to reduce the bounding box. "
"This setting applies only with the natural placement strategy."
msgstr ""
"Опитва се да използва повече от екрана за разполагането на миниатюри на "
"прозорци, като се адаптира към съотношението на страните на екрана и "
"уплътнява подредбата, за да намали ограничителната рамка. Тази настройка се "
"прилага само за метода на естествено разполагане."
"Използване на по-голяма част от екрана за поставянето на мини изображения "
"чрез промяна на съотношението на страните и допълнително обединяване за "
"смаляване на обхващащия ги правоъгълник. Тази настройка се прилага само при "
"естествената стратегия за поставяне на прозорците."
#: extensions/native-window-placement/org.gnome.shell.extensions.native-window-placement.gschema.xml:17
msgid "Place window captions on top"
@@ -110,56 +109,49 @@ msgid ""
"shell default of placing it at the bottom. Changing this setting requires "
"restarting the shell to have any effect."
msgstr ""
"Ако е включено, заглавията на прозорците ще се поставят над съответната "
"миниатюра, вместо по подразбиране в долната ѝ част. За да влезе в сила, тази "
"промяна изисква рестартиране на обвивката на GNOME."
"Ако е истина, заглавията на прозорците се поставят над мини изображенията "
"им, а не както е стандартно — отдолу. За прилагане на промяната на "
"настройката трябва да рестартирате обвивката на GNOME."
#: extensions/places-menu/extension.js:75
#: extensions/places-menu/extension.js:78
#: extensions/places-menu/extension.js:91
#: extensions/places-menu/extension.js:94
msgid "Places"
msgstr "Места"
#: extensions/places-menu/placeDisplay.js:52
#: extensions/places-menu/placeDisplay.js:60
#, javascript-format
msgid "Failed to launch “%s”"
msgstr "Неуспешно стартиране на „%s“"
#: extensions/places-menu/placeDisplay.js:67
#: extensions/places-menu/placeDisplay.js:75
#, javascript-format
msgid "Failed to mount volume for “%s”"
msgstr "Неуспешно монтиране на тома „%s“"
#: extensions/places-menu/placeDisplay.js:315
#: extensions/places-menu/placeDisplay.js:135
#: extensions/places-menu/placeDisplay.js:158
msgid "Computer"
msgstr "Компютър"
#: extensions/places-menu/placeDisplay.js:333
msgid "Home"
msgstr "Домашна папка"
#: extensions/places-menu/placeDisplay.js:321
msgid "Recent"
msgstr "Скорошни"
#: extensions/places-menu/placeDisplay.js:327
msgid "Starred"
msgstr "Отбелязани"
#: extensions/places-menu/placeDisplay.js:347
msgid "Network"
#: extensions/places-menu/placeDisplay.js:378
msgid "Browse Network"
msgstr "Мрежа"
#: extensions/places-menu/placeDisplay.js:354
msgid "Trash"
msgstr "Кошче"
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:14
msgid "Cycle Screenshot Sizes"
msgstr "Превключване между размерите на екранната снимка"
msgstr "Смяна на размерите на снимката на екрана"
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:18
msgid "Cycle Screenshot Sizes Backward"
msgstr "Обратно превключване на размерите на екранната снимка"
msgstr "Смяна на размерите на снимката на екрана наобратно"
#: extensions/system-monitor/extension.js:135
msgid "CPU stats"
msgstr "Статистика на процесора"
msgstr "Статистика на ЦП"
#: extensions/system-monitor/extension.js:159
msgid "Memory stats"
@@ -171,55 +163,55 @@ msgstr "Статистика на виртуалната памет"
#: extensions/system-monitor/extension.js:336
msgid "Upload stats"
msgstr "Статистика за качването"
msgstr "Статистика на качване"
#: extensions/system-monitor/extension.js:350
msgid "Download stats"
msgstr "Статистика за изтеглянето"
msgstr "Статистика на изтегляне"
#: extensions/system-monitor/extension.js:365
#: extensions/system-monitor/extension.js:364
msgid "System stats"
msgstr "Системна статистика"
msgstr "Статистика на системата"
#: extensions/system-monitor/extension.js:413
#: extensions/system-monitor/extension.js:412
msgid "Show"
msgstr "Показване"
#: extensions/system-monitor/extension.js:415
#: extensions/system-monitor/extension.js:414
msgid "CPU"
msgstr "Процесор"
msgstr "ЦП"
#: extensions/system-monitor/extension.js:417
#: extensions/system-monitor/extension.js:416
msgid "Memory"
msgstr "Памет"
#: extensions/system-monitor/extension.js:419
#: extensions/system-monitor/extension.js:418
msgid "Swap"
msgstr "Виртуалната памет"
#: extensions/system-monitor/extension.js:421
#: extensions/system-monitor/extension.js:420
msgid "Upload"
msgstr "Качване"
#: extensions/system-monitor/extension.js:423
#: extensions/system-monitor/extension.js:422
msgid "Download"
msgstr "Изтегляне"
#: extensions/system-monitor/extension.js:428
#: extensions/system-monitor/extension.js:427
msgid "Open System Monitor"
msgstr "Отваряне на „Наблюдение на системата“"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:12
msgid "Show CPU usage"
msgstr "Показване на използването на процесора"
msgstr "Показване на ползван ЦП"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:16
msgid "Show memory usage"
msgstr "Показване на използването на паметта"
msgstr "Показване на ползвана памет"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:20
msgid "Show swap usage"
msgstr "Показване на използването на виртуалната памет"
msgstr "Показване на ползвана виртуалната памет"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:24
msgid "Show upload"
@@ -235,176 +227,125 @@ msgstr "Име на темата"
#: extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml:12
msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell"
msgstr "Името на темата, която да се зареди от „~/.themes/name/gnome-shell“"
msgstr ""
"Името на темата, която да бъде заредена от „~/.themes/name/gnome-shell“"
#: extensions/window-list/extension.js:98
#: extensions/window-list/extension.js:72
msgid "Close"
msgstr "Затваряне"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:99
msgid "Unminimize"
msgstr "Деминимизиране"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:99
msgid "Minimize"
msgstr "Минимизиране"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:106
msgid "Unmaximize"
msgstr "Демаксимизиране"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:106
msgid "Maximize"
msgstr "Максимизиране"
#: extensions/window-list/extension.js:720
#: extensions/window-list/extension.js:471
msgid "Minimize all"
msgstr "Минимизиране на всички"
#: extensions/window-list/extension.js:726
#: extensions/window-list/extension.js:477
msgid "Unminimize all"
msgstr "Деминимизиране на всички"
#: extensions/window-list/extension.js:732
#: extensions/window-list/extension.js:483
msgid "Maximize all"
msgstr "Максимизиране на всички"
#: extensions/window-list/extension.js:740
#: extensions/window-list/extension.js:491
msgid "Unmaximize all"
msgstr "Демаксимизиране на всички"
#: extensions/window-list/extension.js:748
#: extensions/window-list/extension.js:499
msgid "Close all"
msgstr "Затваряне на всички"
#: extensions/window-list/extension.js:1000 extensions/window-list/prefs.js:23
#: extensions/window-list/extension.js:773
msgid "Window List"
msgstr "Списък на прозорците"
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:18
msgid "When to group windows"
msgstr "Кога да се групират прозорците"
msgstr "Кога прозорците да се групират"
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:19
msgid ""
"Decides when to group windows from the same application on the window list. "
"Possible values are “never”, “auto” and “always”."
msgstr ""
"Кога да се групират прозорци от едно и също приложение в списъка с прозорци. "
"Възможните стойности са „никога, „автоматично и „винаги“."
"Кога прозорците на една програма да се групират в списъка с прозорците. "
"Възможните стойности саnever“ (никога), „auto“ (автоматично) и „always“ "
"(винаги)."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:26
#: extensions/window-list/prefs.js:74
#: extensions/window-list/prefs.js:79
msgid "Show windows from all workspaces"
msgstr "Показване на прозорците от всички работни пространства"
msgstr "Да се показват прозорците от всички работни плотове"
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:27
msgid "Whether to show windows from all workspaces or only the current one."
msgstr ""
"Дали да се показват прозорците от всички работни пространства или само от "
"текущото."
"Дали да се показват прозорците от всички работни плотове или само от текущия."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:33
msgid "Show the window list on all monitors"
msgstr "Показване на списъка с прозорци на всички монитори"
msgstr "Извеждане на списъка с прозорци на всички монитори"
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:34
msgid ""
"Whether to show the window list on all connected monitors or only on the "
"primary one."
msgstr ""
"Дали да се показва списъкът с прозорци на всички свързани монитори или само "
"на основния."
"Дали списъкът с прозорци да се извежда на всички монитори или само на "
"основния"
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:41
msgid "Show workspace previews in window list"
msgstr "Показване на прегледа на работните пространства"
#: extensions/window-list/prefs.js:41
#: extensions/window-list/prefs.js:35
msgid "Window Grouping"
msgstr "Групиране на прозорци"
#: extensions/window-list/prefs.js:46
#: extensions/window-list/prefs.js:40
msgid "Never group windows"
msgstr "Никога да не се групират"
#: extensions/window-list/prefs.js:47
#: extensions/window-list/prefs.js:41
msgid "Group windows when space is limited"
msgstr "Групиране при ограничено място"
#: extensions/window-list/prefs.js:48
#: extensions/window-list/prefs.js:42
msgid "Always group windows"
msgstr "Винаги да се групират"
#: extensions/window-list/prefs.js:68
#: extensions/window-list/prefs.js:66
msgid "Show on all monitors"
msgstr "На всички монитори"
#: extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml:12
msgid "Show workspace previews in top bar"
msgstr "Визуализиране на работните пространства в горната лента"
#: extensions/workspace-indicator/workspaceIndicator.js:404
#, javascript-format
msgid "Press %s to edit"
msgstr "Натиснете %s за редактирате"
#: extensions/workspace-indicator/workspaceIndicator.js:518
msgid "Settings"
msgstr "Настройки"
#: extensions/workspace-indicator/workspaceIndicator.js:598
#: extensions/window-list/workspaceIndicator.js:255
#: extensions/workspace-indicator/extension.js:261
msgid "Workspace Indicator"
msgstr "Индикатор на работните пространства"
msgstr "Индикатор на работните плотове"
#: extensions/workspace-indicator/workspacePrefs.js:20
msgid "Indicator"
msgstr "Индикатор"
#: extensions/workspace-indicator/prefs.js:69
#, javascript-format
msgid "Workspace %d"
msgstr "Работен плот %d"
#: extensions/workspace-indicator/workspacePrefs.js:25
msgid "Previews"
msgstr "Прегледи"
#: extensions/workspace-indicator/prefs.js:136
msgid "Workspace Names"
msgstr "Имена на работните плотове"
#: extensions/workspace-indicator/workspacePrefs.js:35
msgid "Workspace Name"
msgstr "Име на работното пространство"
#: extensions/workspace-indicator/workspacePrefs.js:59
msgid "Behavior"
msgstr "Поведение"
#: extensions/workspace-indicator/workspacePrefs.js:64
msgid "Dynamic"
msgstr "Динамично"
#: extensions/workspace-indicator/workspacePrefs.js:65
msgid "Automatically removes empty workspaces."
msgstr "Автоматично премахва празните работни пространства."
#: extensions/workspace-indicator/workspacePrefs.js:75
msgid "Fixed Number"
msgstr "Фиксиран брой"
#: extensions/workspace-indicator/workspacePrefs.js:76
msgid "Specify a number of permanent workspaces."
msgstr "Посочете брой постоянни работни пространства."
#: extensions/workspace-indicator/workspacePrefs.js:89
msgid "Number of Workspaces"
msgstr "Брой работни пространства"
#: extensions/workspace-indicator/workspacePrefs.js:128
msgid "Workspaces"
msgstr "Работни пространства"
#~ msgid "Computer"
#~ msgstr "Компютър"
#~ msgid "Show workspace previews"
#~ msgstr "Визуализиране на работните пространства"
#~ msgid "Show Previews In Top Bar"
#~ msgstr "Визуализиране в горната лента"
#: extensions/workspace-indicator/prefs.js:262
msgid "Add Workspace"
msgstr "Добавяне на работен плот"
#~ msgid "Applications"
#~ msgstr "Програми"

211
po/ca.po
View File

@@ -1,25 +1,22 @@
# 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 <jmas@softcatala.org>, 2011.
# Jordi Mas i Hernàndez <jmas@softcatala.org>, 2011, 2024
# Gil Forcada <gilforcada@guifi.net>, 2012, 2013, 2014.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell-extensions\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
"issues\n"
"POT-Creation-Date: 2025-06-18 23:32+0000\n"
"PO-Revision-Date: 2025-06-29 09:56+0200\n"
"Last-Translator: Jordi Mas <jmas@softcatala.org>\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues\n"
"POT-Creation-Date: 2024-05-23 16:39+0000\n"
"PO-Revision-Date: 2024-05-23 13:29+0100\n"
"Last-Translator: Jordi Mas i Hernàndez <jmas@softcatala.org>\n"
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
"Language: ca\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-DamnedLies-Scope: partial\n"
"X-Generator: Poedit 3.2.2\n"
#: data/gnome-classic.desktop.in:3
msgid "GNOME Classic"
@@ -38,11 +35,11 @@ msgstr "GNOME clàssic amb Wayland"
msgid "GNOME Classic on Xorg"
msgstr "GNOME clàssic amb Xorg"
#: extensions/apps-menu/extension.js:118
#: extensions/apps-menu/extension.js:126
msgid "Favorites"
msgstr "Preferides"
#: extensions/apps-menu/extension.js:392
#: extensions/apps-menu/extension.js:400
msgid "Apps"
msgstr "Aplicacions"
@@ -59,17 +56,17 @@ msgstr ""
"d'aplicació (nom del fitxer de l'escriptori), seguit de dos punts i el "
"número de l'espai de treball"
#: extensions/auto-move-windows/prefs.js:156
#: extensions/auto-move-windows/prefs.js:159
msgid "Workspace Rules"
msgstr "Regles dels espais de treball"
#: extensions/auto-move-windows/prefs.js:311
#: extensions/auto-move-windows/prefs.js:314
msgid "Add Rule"
msgstr "Afegeix una regla"
#. TRANSLATORS: %s is the filesystem name
#: extensions/drive-menu/extension.js:123
#: extensions/places-menu/placeDisplay.js:186
#: extensions/places-menu/placeDisplay.js:218
#, javascript-format
msgid "Ejecting drive “%s” failed:"
msgstr "Ha fallat l'expulsió de la unitat «%s»:"
@@ -109,44 +106,37 @@ msgid ""
"restarting the shell to have any effect."
msgstr ""
"Si és «true» (cert), posiciona el títol de la finestra damunt de la "
"miniatura corresponent, substituint el comportament per defecte del Shell de "
"posicionar-lo a baix. Cal reiniciar el Shell per tal que aquest canvi tingui "
"efecte."
"miniatura corresponent, substituint el comportament per defecte del Shell de"
" posicionar-lo a baix. Cal reiniciar el Shell per tal que aquest canvi "
"tingui efecte."
#: extensions/places-menu/extension.js:75
#: extensions/places-menu/extension.js:78
#: extensions/places-menu/extension.js:91
#: extensions/places-menu/extension.js:94
msgid "Places"
msgstr "Llocs"
#: extensions/places-menu/placeDisplay.js:52
#: extensions/places-menu/placeDisplay.js:60
#, javascript-format
msgid "Failed to launch “%s”"
msgstr "No s'ha pogut iniciar «%s»"
#: extensions/places-menu/placeDisplay.js:67
#: extensions/places-menu/placeDisplay.js:75
#, javascript-format
msgid "Failed to mount volume for “%s”"
msgstr "No s'ha pogut muntar el volum «%s»"
#: extensions/places-menu/placeDisplay.js:315
#: extensions/places-menu/placeDisplay.js:135
#: extensions/places-menu/placeDisplay.js:158
msgid "Computer"
msgstr "Ordinador"
#: extensions/places-menu/placeDisplay.js:333
msgid "Home"
msgstr "Inici"
#: extensions/places-menu/placeDisplay.js:321
msgid "Recent"
msgstr "Recent"
#: extensions/places-menu/placeDisplay.js:327
msgid "Starred"
msgstr "Destacat"
#: extensions/places-menu/placeDisplay.js:347
msgid "Network"
msgstr "Xarxa"
#: extensions/places-menu/placeDisplay.js:354
msgid "Trash"
msgstr "Paperera"
#: extensions/places-menu/placeDisplay.js:378
msgid "Browse Network"
msgstr "Navega per la xarxa"
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:14
msgid "Cycle Screenshot Sizes"
@@ -158,7 +148,7 @@ msgstr "Mostra cíclicament cap enrere mides de captura de pantalla"
#: extensions/system-monitor/extension.js:135
msgid "CPU stats"
msgstr "Estadístiques de processador"
msgstr "Estadístiques de la CPU"
#: extensions/system-monitor/extension.js:159
msgid "Memory stats"
@@ -166,7 +156,7 @@ msgstr "Estadístiques de memòria"
#: extensions/system-monitor/extension.js:177
msgid "Swap stats"
msgstr "Estadístiques del «swap»"
msgstr "Estadístiques de l'intercanvi"
#: extensions/system-monitor/extension.js:336
msgid "Upload stats"
@@ -174,7 +164,7 @@ msgstr "Estadístiques de pujada"
#: extensions/system-monitor/extension.js:350
msgid "Download stats"
msgstr "Estadístiques de descàrrega"
msgstr "Estadístiques de baixada"
#: extensions/system-monitor/extension.js:364
msgid "System stats"
@@ -186,7 +176,7 @@ msgstr "Mostra"
#: extensions/system-monitor/extension.js:414
msgid "CPU"
msgstr "Processador"
msgstr "CPU"
#: extensions/system-monitor/extension.js:416
msgid "Memory"
@@ -194,39 +184,39 @@ msgstr "Memòria"
#: extensions/system-monitor/extension.js:418
msgid "Swap"
msgstr "Espai d'intercanvi"
msgstr "Intercanvi"
#: extensions/system-monitor/extension.js:420
msgid "Upload"
msgstr "Pujades"
msgstr "Pujada"
#: extensions/system-monitor/extension.js:422
msgid "Download"
msgstr "Descàrregues"
msgstr "Baixada"
#: extensions/system-monitor/extension.js:427
msgid "Open System Monitor"
msgstr "Obre el Monitor del sistema"
msgstr "Obre el monitor del sistema"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:12
msgid "Show CPU usage"
msgstr "Mostra l'ús de CPU"
msgstr "Mostra l'ús de la CPU"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:16
msgid "Show memory usage"
msgstr "Mostra l'ús de memòria"
msgstr "Mostra l'ús de la memòria"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:20
msgid "Show swap usage"
msgstr "Mostra l'ús de l'espai d'intercanvi"
msgstr "Mostra l'ús d'intercanvi"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:24
msgid "Show upload"
msgstr "Mostra les pujades"
msgstr "Mostra la pujada"
#: extensions/system-monitor/schemas/org.gnome.shell.extensions.system-monitor.gschema.xml:28
msgid "Show download"
msgstr "Mostra les descàrregues"
msgstr "Mostra la baixada"
#: extensions/user-theme/org.gnome.shell.extensions.user-theme.gschema.xml:11
msgid "Theme name"
@@ -236,47 +226,47 @@ msgstr "Nom del tema"
msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell"
msgstr "El nom del tema que es carregarà des de ~/.themes/name/gnome-shell"
#: extensions/window-list/extension.js:98
#: extensions/window-list/extension.js:72
msgid "Close"
msgstr "Tanca"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:99
msgid "Unminimize"
msgstr "Desminimitza"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:99
msgid "Minimize"
msgstr "Minimitza"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:106
msgid "Unmaximize"
msgstr "Desmaximitza"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:106
msgid "Maximize"
msgstr "Maximitza"
#: extensions/window-list/extension.js:720
#: extensions/window-list/extension.js:471
msgid "Minimize all"
msgstr "Minimitza-ho tot"
#: extensions/window-list/extension.js:726
#: extensions/window-list/extension.js:477
msgid "Unminimize all"
msgstr "Desminimitza-ho tot"
#: extensions/window-list/extension.js:732
#: extensions/window-list/extension.js:483
msgid "Maximize all"
msgstr "Maximitza-ho tot"
#: extensions/window-list/extension.js:740
#: extensions/window-list/extension.js:491
msgid "Unmaximize all"
msgstr "Desmaximitza-ho tot"
#: extensions/window-list/extension.js:748
#: extensions/window-list/extension.js:499
msgid "Close all"
msgstr "Tanca-ho tot"
#: extensions/window-list/extension.js:1000 extensions/window-list/prefs.js:23
#: extensions/window-list/extension.js:773
msgid "Window List"
msgstr "Llista de finestres"
@@ -290,11 +280,11 @@ msgid ""
"Possible values are “never”, “auto” and “always”."
msgstr ""
"Decideix quan s'han d'agrupar les finestres de la mateixa aplicació a la "
"llista de finestres. Els valors possibles són: «never» (mai), "
"«auto» (automàticament) i «always» (sempre)."
"llista de finestres. Els valors possibles són: «never» (mai), «auto» "
"(automàticament) i «always» (sempre)."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:26
#: extensions/window-list/prefs.js:74
#: extensions/window-list/prefs.js:79
msgid "Show windows from all workspaces"
msgstr "Mostra les finestres de tots els espais de treball"
@@ -316,104 +306,41 @@ msgstr ""
"Si es mostra la llista de finestres en tots els monitors connectats o només "
"al primari."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:41
msgid "Show workspace previews in window list"
msgstr ""
"Mostra les previsualitzacions dels espais de treball a la llista de finestres"
#: extensions/window-list/prefs.js:41
#: extensions/window-list/prefs.js:35
msgid "Window Grouping"
msgstr "Agrupació de finestres"
#: extensions/window-list/prefs.js:46
#: extensions/window-list/prefs.js:40
msgid "Never group windows"
msgstr "Mai agrupis les finestres"
#: extensions/window-list/prefs.js:47
#: extensions/window-list/prefs.js:41
msgid "Group windows when space is limited"
msgstr "Agrupa les finestres quan l'espai estigui limitat"
#: extensions/window-list/prefs.js:48
#: extensions/window-list/prefs.js:42
msgid "Always group windows"
msgstr "Agrupa les finestres sempre"
#: extensions/window-list/prefs.js:68
#: extensions/window-list/prefs.js:66
msgid "Show on all monitors"
msgstr "Mostra a tots els monitors"
#: extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml:12
msgid "Show workspace previews in top bar"
msgstr ""
"Mostra les previsualitzacions dels espais de treball a la barra superior"
#: extensions/workspace-indicator/workspaceIndicator.js:404
#, javascript-format
msgid "Press %s to edit"
msgstr "Premeu %s per editar"
#: extensions/workspace-indicator/workspaceIndicator.js:512
msgid "Settings"
msgstr "Paràmetres"
#: extensions/workspace-indicator/workspaceIndicator.js:592
#: extensions/window-list/workspaceIndicator.js:255
#: extensions/workspace-indicator/extension.js:261
msgid "Workspace Indicator"
msgstr "Indicador de l'espai de treball"
#: extensions/workspace-indicator/workspacePrefs.js:20
msgid "Indicator"
msgstr "Indicador"
#: extensions/workspace-indicator/workspacePrefs.js:25
msgid "Previews"
msgstr "Previsualitzacions"
#: extensions/workspace-indicator/workspacePrefs.js:35
msgid "Workspace Name"
msgstr "Nom de l'espai de treball"
#: extensions/workspace-indicator/workspacePrefs.js:59
msgid "Behavior"
msgstr "Comportament"
#: extensions/workspace-indicator/workspacePrefs.js:64
msgid "Dynamic"
msgstr "Dinàmica"
#: extensions/workspace-indicator/workspacePrefs.js:65
msgid "Automatically removes empty workspaces."
msgstr "Suprimeix automàticament els espais de treball buits."
#: extensions/workspace-indicator/workspacePrefs.js:75
msgid "Fixed Number"
msgstr "Nombre fix"
#: extensions/workspace-indicator/workspacePrefs.js:76
msgid "Specify a number of permanent workspaces."
msgstr "Especifiqueu un nombre d'espais de treball permanents."
#: extensions/workspace-indicator/workspacePrefs.js:89
msgid "Number of Workspaces"
msgstr "Nombre d'espais de treball"
#: extensions/workspace-indicator/workspacePrefs.js:128
msgid "Workspaces"
msgstr "Espais de treball"
#: extensions/workspace-indicator/prefs.js:69
#, javascript-format
#~ msgid "Workspace %d"
#~ msgstr "Espai de treball %d"
msgid "Workspace %d"
msgstr "Espai de treball %d"
#~ msgid "Add Workspace"
#~ msgstr "Afegeix un espai de treball"
#: extensions/workspace-indicator/prefs.js:136
msgid "Workspace Names"
msgstr "Noms dels espais de treball"
#~ msgid "Remove"
#~ msgstr "Suprimeix"
#: extensions/workspace-indicator/prefs.js:262
msgid "Add Workspace"
msgstr "Afegeix un espai de treball"
#~ msgid "Computer"
#~ msgstr "Ordinador"
#~ msgid "Show workspace previews"
#~ msgstr "Mostra les previsualitzacions dels espais de treball"
#~ msgid "Applications"
#~ msgstr "Aplicacions"

195
po/cs.po
View File

@@ -3,15 +3,14 @@
# This file is distributed under the same license as the gnome-shell-extensions package.
# Petr Kovar <pknbe@volny.cz>, 2013.
# Marek Černocký <marek@manet.cz>, 2011, 2012, 2013, 2014, 2015, 2017, 2019, 2020, 2022.
# Vojtěch Perník <translations@pervoj.cz>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell-extensions\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
"issues\n"
"POT-Creation-Date: 2025-08-14 10:26+0000\n"
"PO-Revision-Date: 2025-08-18 23:54+0200\n"
"POT-Creation-Date: 2024-02-06 18:43+0000\n"
"PO-Revision-Date: 2024-02-07 15:08+0100\n"
"Last-Translator: Daniel Rusek <mail@asciiwolf.com>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"Language: cs\n"
@@ -19,30 +18,30 @@ msgstr ""
"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 3.6\n"
"X-Generator: Poedit 3.4.2\n"
#: data/gnome-classic.desktop.in:2
#: data/gnome-classic.desktop.in:3
msgid "GNOME Classic"
msgstr "GNOME klasik"
#: data/gnome-classic.desktop.in:3 data/gnome-classic-wayland.desktop.in:3
#: data/gnome-classic-xorg.desktop.in:3
#: data/gnome-classic.desktop.in:4 data/gnome-classic-wayland.desktop.in:4
#: data/gnome-classic-xorg.desktop.in:4
msgid "This session logs you into GNOME Classic"
msgstr "Toto sezení vás přihlásí do GNOME klasik"
#: data/gnome-classic-wayland.desktop.in:2
#: data/gnome-classic-wayland.desktop.in:3
msgid "GNOME Classic on Wayland"
msgstr "GNOME klasik na Waylandu"
#: data/gnome-classic-xorg.desktop.in:2
#: data/gnome-classic-xorg.desktop.in:3
msgid "GNOME Classic on Xorg"
msgstr "GNOME klasik na Xorg"
#: extensions/apps-menu/extension.js:118
#: extensions/apps-menu/extension.js:126
msgid "Favorites"
msgstr "Oblíbené"
#: extensions/apps-menu/extension.js:392
#: extensions/apps-menu/extension.js:397
msgid "Apps"
msgstr "Aplikace"
@@ -58,17 +57,17 @@ msgstr ""
"Seznam řetězců, z nichž každý obsahuje ID aplikace (název souboru pracovní "
"plochy), následovaný dvojtečkou a číslem pracovní plochy"
#: extensions/auto-move-windows/prefs.js:156
#: extensions/auto-move-windows/prefs.js:159
msgid "Workspace Rules"
msgstr "Pravidla pracovních ploch"
#: extensions/auto-move-windows/prefs.js:311
#: extensions/auto-move-windows/prefs.js:314
msgid "Add Rule"
msgstr "Přidat pravidlo"
#. TRANSLATORS: %s is the filesystem name
#: extensions/drive-menu/extension.js:123
#: extensions/places-menu/placeDisplay.js:186
#: extensions/places-menu/placeDisplay.js:218
#, javascript-format
msgid "Ejecting drive “%s” failed:"
msgstr "Vysunutí disku „%s“ selhalo:"
@@ -109,40 +108,33 @@ msgstr ""
"přepíše výchozí chování shellu, který jej umisťuje dolů. Změna tohoto "
"nastavení vyžaduje restart shellu, aby se projevila."
#: extensions/places-menu/extension.js:75
#: extensions/places-menu/extension.js:78
#: extensions/places-menu/extension.js:91
#: extensions/places-menu/extension.js:94
msgid "Places"
msgstr "Místa"
#: extensions/places-menu/placeDisplay.js:52
#: extensions/places-menu/placeDisplay.js:60
#, javascript-format
msgid "Failed to launch “%s”"
msgstr "Selhalo spuštění „%s“"
#: extensions/places-menu/placeDisplay.js:67
#: extensions/places-menu/placeDisplay.js:75
#, javascript-format
msgid "Failed to mount volume for “%s”"
msgstr "Selhalo připojení svazku pro „%s“"
#: extensions/places-menu/placeDisplay.js:315
#: extensions/places-menu/placeDisplay.js:135
#: extensions/places-menu/placeDisplay.js:158
msgid "Computer"
msgstr "Počítač"
#: extensions/places-menu/placeDisplay.js:333
msgid "Home"
msgstr "Domů"
#: extensions/places-menu/placeDisplay.js:321
msgid "Recent"
msgstr "Nedávné"
#: extensions/places-menu/placeDisplay.js:327
msgid "Starred"
msgstr "Oblíbené"
#: extensions/places-menu/placeDisplay.js:347
msgid "Network"
msgstr "Síť"
#: extensions/places-menu/placeDisplay.js:354
msgid "Trash"
msgstr "Koš"
#: extensions/places-menu/placeDisplay.js:378
msgid "Browse Network"
msgstr "Procházet síť"
#: extensions/screenshot-window-sizer/org.gnome.shell.extensions.screenshot-window-sizer.gschema.xml:14
msgid "Cycle Screenshot Sizes"
@@ -164,43 +156,43 @@ msgstr "Statistiky paměti"
msgid "Swap stats"
msgstr "Statistiky odkládacího prostoru"
#: extensions/system-monitor/extension.js:336
#: extensions/system-monitor/extension.js:327
msgid "Upload stats"
msgstr "Statistiky nahrávání"
#: extensions/system-monitor/extension.js:350
#: extensions/system-monitor/extension.js:341
msgid "Download stats"
msgstr "Statistiky stahování"
#: extensions/system-monitor/extension.js:364
#: extensions/system-monitor/extension.js:355
msgid "System stats"
msgstr "Statistiky systému"
#: extensions/system-monitor/extension.js:412
#: extensions/system-monitor/extension.js:403
msgid "Show"
msgstr "Zobrazit"
#: extensions/system-monitor/extension.js:414
#: extensions/system-monitor/extension.js:405
msgid "CPU"
msgstr "CPU"
#: extensions/system-monitor/extension.js:416
#: extensions/system-monitor/extension.js:407
msgid "Memory"
msgstr "Paměť"
#: extensions/system-monitor/extension.js:418
#: extensions/system-monitor/extension.js:409
msgid "Swap"
msgstr "Odkládací prostor"
#: extensions/system-monitor/extension.js:420
#: extensions/system-monitor/extension.js:411
msgid "Upload"
msgstr "Nahrávání"
#: extensions/system-monitor/extension.js:422
#: extensions/system-monitor/extension.js:413
msgid "Download"
msgstr "Stahování"
#: extensions/system-monitor/extension.js:427
#: extensions/system-monitor/extension.js:418
msgid "Open System Monitor"
msgstr "Otevřít Sledování systému"
@@ -232,47 +224,47 @@ msgstr "Název motivu"
msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell"
msgstr "Název motivu, který se má načíst z ~/.themes/name/gnome-shell"
#: extensions/window-list/extension.js:98
#: extensions/window-list/extension.js:71
msgid "Close"
msgstr "Zavřít"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:98
msgid "Unminimize"
msgstr "Zrušit minimalizaci"
#: extensions/window-list/extension.js:125
#: extensions/window-list/extension.js:98
msgid "Minimize"
msgstr "Minimalizovat"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:105
msgid "Unmaximize"
msgstr "Zrušit maximalizaci"
#: extensions/window-list/extension.js:130
#: extensions/window-list/extension.js:105
msgid "Maximize"
msgstr "Maximalizovat"
#: extensions/window-list/extension.js:720
#: extensions/window-list/extension.js:470
msgid "Minimize all"
msgstr "Minimalizovat všechna"
#: extensions/window-list/extension.js:726
#: extensions/window-list/extension.js:476
msgid "Unminimize all"
msgstr "Zrušit minimalizaci všech"
#: extensions/window-list/extension.js:732
#: extensions/window-list/extension.js:482
msgid "Maximize all"
msgstr "Maximalizovat všechna"
#: extensions/window-list/extension.js:740
#: extensions/window-list/extension.js:490
msgid "Unmaximize all"
msgstr "Zrušit maximalizaci všech"
#: extensions/window-list/extension.js:748
#: extensions/window-list/extension.js:498
msgid "Close all"
msgstr "Zavřít všechna"
#: extensions/window-list/extension.js:1000 extensions/window-list/prefs.js:23
#: extensions/window-list/extension.js:772
msgid "Window List"
msgstr "Seznam oken"
@@ -289,7 +281,7 @@ msgstr ""
"hodnoty jsou „never“ (nikdy), „auto“ (automaticky) a „always“ (vždy)."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:26
#: extensions/window-list/prefs.js:74
#: extensions/window-list/prefs.js:79
msgid "Show windows from all workspaces"
msgstr "Zobrazovat okna ze všech pracovních ploch"
@@ -309,102 +301,43 @@ msgstr ""
"Zda zobrazovat seznam oken na všech připojených monitorech nebo jen na "
"hlavním."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:41
msgid "Show workspace previews in window list"
msgstr "Zobrazit náhledy pracovních ploch v seznamu oken"
#: extensions/window-list/prefs.js:41
#: extensions/window-list/prefs.js:35
msgid "Window Grouping"
msgstr "Seskupování oken"
#: extensions/window-list/prefs.js:46
#: extensions/window-list/prefs.js:40
msgid "Never group windows"
msgstr "Nikdy neseskupovat okna"
#: extensions/window-list/prefs.js:47
#: extensions/window-list/prefs.js:41
msgid "Group windows when space is limited"
msgstr "Seskupovat okna při nedostatku místa"
#: extensions/window-list/prefs.js:48
#: extensions/window-list/prefs.js:42
msgid "Always group windows"
msgstr "Vždy seskupovat okna"
#: extensions/window-list/prefs.js:68
#: extensions/window-list/prefs.js:66
msgid "Show on all monitors"
msgstr "Zobrazovat na všech monitorech"
#: extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml:12
msgid "Show workspace previews in top bar"
msgstr "Zobrazit náhledy pracovních ploch v horním panelu"
#: extensions/workspace-indicator/workspaceIndicator.js:404
#, javascript-format
msgid "Press %s to edit"
msgstr "Stiskněte %s pro úpravu"
#: extensions/workspace-indicator/workspaceIndicator.js:512
msgid "Settings"
msgstr "Nastavení"
#: extensions/workspace-indicator/workspaceIndicator.js:592
#: extensions/window-list/workspaceIndicator.js:253
#: extensions/workspace-indicator/extension.js:259
msgid "Workspace Indicator"
msgstr "Ukazatel pracovní plochy"
#: extensions/workspace-indicator/workspacePrefs.js:20
msgid "Indicator"
msgstr "Ukazatel"
#: extensions/workspace-indicator/workspacePrefs.js:25
msgid "Previews"
msgstr "Náhledy"
#: extensions/workspace-indicator/workspacePrefs.js:35
msgid "Workspace Name"
msgstr "Název pracovní plochy"
#: extensions/workspace-indicator/workspacePrefs.js:59
msgid "Behavior"
msgstr "Chování"
#: extensions/workspace-indicator/workspacePrefs.js:64
msgid "Dynamic"
msgstr "Dynamické"
#: extensions/workspace-indicator/workspacePrefs.js:65
msgid "Automatically removes empty workspaces."
msgstr "Bude automaticky odebírat prázdné pracovní plochy."
#: extensions/workspace-indicator/workspacePrefs.js:75
msgid "Fixed Number"
msgstr "Neměnný počet"
#: extensions/workspace-indicator/workspacePrefs.js:76
msgid "Specify a number of permanent workspaces."
msgstr "Určit počet trvalých pracovních ploch."
#: extensions/workspace-indicator/workspacePrefs.js:89
msgid "Number of Workspaces"
msgstr "Počet pracovních ploch"
#: extensions/workspace-indicator/workspacePrefs.js:128
msgid "Workspaces"
msgstr "Pracovní plochy"
#: extensions/workspace-indicator/prefs.js:69
#, javascript-format
#~ msgid "Workspace %d"
#~ msgstr "Pracovní plocha %d"
msgid "Workspace %d"
msgstr "Pracovní plocha %d"
#~ msgid "Add Workspace"
#~ msgstr "Přidat pracovní plochu"
#: extensions/workspace-indicator/prefs.js:136
msgid "Workspace Names"
msgstr "Názvy pracovních ploch"
#~ msgid "Remove"
#~ msgstr "Odstranit"
#~ msgid "Computer"
#~ msgstr "Počítač"
#~ msgid "Show workspace previews"
#~ msgstr "Zobrazit náhledy pracovních ploch"
#: extensions/workspace-indicator/prefs.js:262
msgid "Add Workspace"
msgstr "Přidat pracovní plochu"
#~ msgid "Applications"
#~ msgstr "Aplikace"

View File

@@ -9,10 +9,9 @@
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell-extensions master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
"issues\n"
"POT-Creation-Date: 2024-04-29 15:27+0000\n"
"PO-Revision-Date: 2024-09-07 23:22+0200\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues\n"
"POT-Creation-Date: 2024-02-06 18:43+0000\n"
"PO-Revision-Date: 2024-03-12 19:56+0100\n"
"Last-Translator: Ask Hjorth Larsen <asklarsen@gmail.com>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
"Language: da\n"
@@ -43,7 +42,7 @@ msgstr "GNOME Classic på Xorg"
msgid "Favorites"
msgstr "Favoritter"
#: extensions/apps-menu/extension.js:400
#: extensions/apps-menu/extension.js:397
msgid "Apps"
msgstr "Programmer"
@@ -160,43 +159,43 @@ msgstr "Hukommelsesstatistik"
msgid "Swap stats"
msgstr "Swapstatistik"
#: extensions/system-monitor/extension.js:336
#: extensions/system-monitor/extension.js:327
msgid "Upload stats"
msgstr "Uploadstatistik"
#: extensions/system-monitor/extension.js:350
#: extensions/system-monitor/extension.js:341
msgid "Download stats"
msgstr "Downloadstatistik"
#: extensions/system-monitor/extension.js:364
#: extensions/system-monitor/extension.js:355
msgid "System stats"
msgstr "Systemstatistik"
#: extensions/system-monitor/extension.js:412
#: extensions/system-monitor/extension.js:403
msgid "Show"
msgstr "Vis"
#: extensions/system-monitor/extension.js:414
#: extensions/system-monitor/extension.js:405
msgid "CPU"
msgstr "CPU"
#: extensions/system-monitor/extension.js:416
#: extensions/system-monitor/extension.js:407
msgid "Memory"
msgstr "Hukommelse"
#: extensions/system-monitor/extension.js:418
#: extensions/system-monitor/extension.js:409
msgid "Swap"
msgstr "Swap"
#: extensions/system-monitor/extension.js:420
#: extensions/system-monitor/extension.js:411
msgid "Upload"
msgstr "Upload"
#: extensions/system-monitor/extension.js:422
#: extensions/system-monitor/extension.js:413
msgid "Download"
msgstr "Download"
#: extensions/system-monitor/extension.js:427
#: extensions/system-monitor/extension.js:418
msgid "Open System Monitor"
msgstr "Åbn Systemovervågning"
@@ -228,47 +227,47 @@ msgstr "Temanavn"
msgid "The name of the theme, to be loaded from ~/.themes/name/gnome-shell"
msgstr "Navnet på temaet, som indlæses fra ~/.themes/name/gnome-shell"
#: extensions/window-list/extension.js:72
#: extensions/window-list/extension.js:71
msgid "Close"
msgstr "Luk"
#: extensions/window-list/extension.js:99
#: extensions/window-list/extension.js:98
msgid "Unminimize"
msgstr "Afminimér"
#: extensions/window-list/extension.js:99
#: extensions/window-list/extension.js:98
msgid "Minimize"
msgstr "Minimér"
#: extensions/window-list/extension.js:106
#: extensions/window-list/extension.js:105
msgid "Unmaximize"
msgstr "Afmaksimér"
#: extensions/window-list/extension.js:106
#: extensions/window-list/extension.js:105
msgid "Maximize"
msgstr "Maksimér"
#: extensions/window-list/extension.js:471
#: extensions/window-list/extension.js:470
msgid "Minimize all"
msgstr "Minimér"
#: extensions/window-list/extension.js:477
#: extensions/window-list/extension.js:476
msgid "Unminimize all"
msgstr "Afminimér alle"
#: extensions/window-list/extension.js:483
#: extensions/window-list/extension.js:482
msgid "Maximize all"
msgstr "Maksimér alle"
#: extensions/window-list/extension.js:491
#: extensions/window-list/extension.js:490
msgid "Unmaximize all"
msgstr "Afmaksimér alle"
#: extensions/window-list/extension.js:499
#: extensions/window-list/extension.js:498
msgid "Close all"
msgstr "Luk alle"
#: extensions/window-list/extension.js:778
#: extensions/window-list/extension.js:772
msgid "Window List"
msgstr "Vinduesliste"
@@ -306,10 +305,6 @@ msgstr ""
"Om vindueslisten skal vise på alle tilsluttede skærme, eller kun på den "
"primære."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:41
msgid "Show workspace previews in window list"
msgstr "Forhåndsvis arbejdsområder i vinduesliste"
#: extensions/window-list/prefs.js:35
msgid "Window Grouping"
msgstr "Vinduesgruppering"
@@ -330,35 +325,24 @@ msgstr "Gruppér altid vinduer"
msgid "Show on all monitors"
msgstr "Vis på alle skærme"
#: extensions/window-list/prefs.js:92
msgid "Show workspace previews"
msgstr "Forhåndsvis arbejdsområder"
#: extensions/window-list/workspaceIndicator.js:253
#: extensions/workspace-indicator/extension.js:259
msgid "Workspace Indicator"
msgstr "Arbejdsområdeindikator"
#: extensions/workspace-indicator/prefs.js:30
msgid "Show Previews In Top Bar"
msgstr "Inkludér forhåndsvisninger i topbjælken"
#: extensions/workspace-indicator/prefs.js:88
#: extensions/workspace-indicator/prefs.js:69
#, javascript-format
msgid "Workspace %d"
msgstr "Arbejdsområde %d"
#: extensions/workspace-indicator/prefs.js:155
#: extensions/workspace-indicator/prefs.js:136
msgid "Workspace Names"
msgstr "Navne på arbejdsområder"
#: extensions/workspace-indicator/prefs.js:281
#: extensions/workspace-indicator/prefs.js:262
msgid "Add Workspace"
msgstr "Tilføj arbejdsområde"
#: extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml:12
msgid "Show workspace previews in top bar"
msgstr "Inkludér forhåndsvisninger af arbejdsområder i topbjælken"
#: extensions/workspace-indicator/workspaceIndicator.js:430
msgid "Workspace Indicator"
msgstr "Arbejdsområdeindikator"
#~ msgid "Applications"
#~ msgstr "Programmer"

View File

@@ -9,23 +9,22 @@
# Tim Sabsch <tim@sabsch.com>, 2019-2020.
# Philipp Kiemle <philipp.kiemle@gmail.com>, 2022.
# Gabriel Brand <gabr.brand@gmail.com>, 2024.
# Jürgen Benvenuti <gastornis@posteo.org>, 2024.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell-extensions main\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/"
"issues\n"
"POT-Creation-Date: 2024-04-29 15:27+0000\n"
"PO-Revision-Date: 2024-08-29 10:01+0200\n"
"Last-Translator: Jürgen Benvenuti <gastornis@posteo.org>\n"
"POT-Creation-Date: 2024-02-06 18:43+0000\n"
"PO-Revision-Date: 2024-02-07 20:42+0100\n"
"Last-Translator: Gabriel Brand <gabr.brand@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\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 3.4.4\n"
"X-Generator: Poedit 3.4.2\n"
#: data/gnome-classic.desktop.in:3
msgid "GNOME Classic"
@@ -48,7 +47,7 @@ msgstr "GNOME Classic unter Xorg"
msgid "Favorites"
msgstr "Favoriten"
#: extensions/apps-menu/extension.js:400
#: extensions/apps-menu/extension.js:397
msgid "Apps"
msgstr "Anwendungen"
@@ -166,43 +165,43 @@ msgstr "Speicherstatistiken"
msgid "Swap stats"
msgstr "Auslagerungsspeicherstatistiken"
#: extensions/system-monitor/extension.js:336
#: extensions/system-monitor/extension.js:327
msgid "Upload stats"
msgstr "Upload-Statistiken"
#: extensions/system-monitor/extension.js:350
#: extensions/system-monitor/extension.js:341
msgid "Download stats"
msgstr "Download-Statistiken"
#: extensions/system-monitor/extension.js:364
#: extensions/system-monitor/extension.js:355
msgid "System stats"
msgstr "Systemstatistiken"
#: extensions/system-monitor/extension.js:412
#: extensions/system-monitor/extension.js:403
msgid "Show"
msgstr "Anzeigen"
#: extensions/system-monitor/extension.js:414
#: extensions/system-monitor/extension.js:405
msgid "CPU"
msgstr "CPU"
#: extensions/system-monitor/extension.js:416
#: extensions/system-monitor/extension.js:407
msgid "Memory"
msgstr "Speicher"
#: extensions/system-monitor/extension.js:418
#: extensions/system-monitor/extension.js:409
msgid "Swap"
msgstr "Auslagerungsspeicher"
#: extensions/system-monitor/extension.js:420
#: extensions/system-monitor/extension.js:411
msgid "Upload"
msgstr "Upload"
#: extensions/system-monitor/extension.js:422
#: extensions/system-monitor/extension.js:413
msgid "Download"
msgstr "Download"
#: extensions/system-monitor/extension.js:427
#: extensions/system-monitor/extension.js:418
msgid "Open System Monitor"
msgstr "Systemüberwachung öffnen"
@@ -236,47 +235,47 @@ msgstr ""
"Der Name des Themas, welches aus ~/.themes/name/gnome-shell geladen werden "
"soll"
#: extensions/window-list/extension.js:72
#: extensions/window-list/extension.js:71
msgid "Close"
msgstr "Schließen"
#: extensions/window-list/extension.js:99
#: extensions/window-list/extension.js:98
msgid "Unminimize"
msgstr "Minimieren rückgängig"
#: extensions/window-list/extension.js:99
#: extensions/window-list/extension.js:98
msgid "Minimize"
msgstr "Minimieren"
#: extensions/window-list/extension.js:106
#: extensions/window-list/extension.js:105
msgid "Unmaximize"
msgstr "Maximieren rückgängig"
#: extensions/window-list/extension.js:106
#: extensions/window-list/extension.js:105
msgid "Maximize"
msgstr "Maximieren"
#: extensions/window-list/extension.js:471
#: extensions/window-list/extension.js:470
msgid "Minimize all"
msgstr "Alle minimieren"
#: extensions/window-list/extension.js:477
#: extensions/window-list/extension.js:476
msgid "Unminimize all"
msgstr "Alle minimieren rückgängig"
#: extensions/window-list/extension.js:483
#: extensions/window-list/extension.js:482
msgid "Maximize all"
msgstr "Alle maximieren"
#: extensions/window-list/extension.js:491
#: extensions/window-list/extension.js:490
msgid "Unmaximize all"
msgstr "Alle maximieren rückgängig"
#: extensions/window-list/extension.js:499
#: extensions/window-list/extension.js:498
msgid "Close all"
msgstr "Alle schließen"
#: extensions/window-list/extension.js:778
#: extensions/window-list/extension.js:772
msgid "Window List"
msgstr "Fensterliste"
@@ -316,10 +315,6 @@ msgstr ""
"Legt fest, ob die Fensterliste auf allen angeschlossenen Bildschirmen "
"angezeigt wird oder nur auf dem Primären."
#: extensions/window-list/org.gnome.shell.extensions.window-list.gschema.xml:41
msgid "Show workspace previews in window list"
msgstr "Arbeitsflächenvorschauen in der Fensterliste anzeigen"
#: extensions/window-list/prefs.js:35
msgid "Window Grouping"
msgstr "Fenstergruppierung"
@@ -340,34 +335,23 @@ msgstr "Fenster immer gruppieren"
msgid "Show on all monitors"
msgstr "Auf allen Bildschirmen anzeigen"
#: extensions/window-list/prefs.js:92
msgid "Show workspace previews"
msgstr "Arbeitsflächenvorschauen anzeigen"
#: extensions/window-list/workspaceIndicator.js:253
#: extensions/workspace-indicator/extension.js:259
msgid "Workspace Indicator"
msgstr "Arbeitsflächenindikator"
#: extensions/workspace-indicator/prefs.js:30
msgid "Show Previews In Top Bar"
msgstr "Vorschauen in der oberen Leiste anzeigen"
#: extensions/workspace-indicator/prefs.js:88
#: extensions/workspace-indicator/prefs.js:69
#, javascript-format
msgid "Workspace %d"
msgstr "Arbeitsfläche %d"
#: extensions/workspace-indicator/prefs.js:155
#: extensions/workspace-indicator/prefs.js:136
msgid "Workspace Names"
msgstr "Namen der Arbeitsflächen"
#: extensions/workspace-indicator/prefs.js:281
#: extensions/workspace-indicator/prefs.js:262
msgid "Add Workspace"
msgstr "Arbeitsfläche hinzufügen"
#: extensions/workspace-indicator/schemas/org.gnome.shell.extensions.workspace-indicator.gschema.xml:12
msgid "Show workspace previews in top bar"
msgstr "Arbeitsflächenvorschauen in der oberen Leiste anzeigen"
#: extensions/workspace-indicator/workspaceIndicator.js:430
msgid "Workspace Indicator"
msgstr "Arbeitsflächenindikator"
#~ msgid "Applications"
#~ msgstr "Anwendungen"

Some files were not shown because too many files have changed in this diff Show More