Compare commits

...

688 Commits

Author SHA1 Message Date
Florian Müllner
fac3d8b8c4 Bump version to 42.alpha
Update NEWS.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/206>
2022-01-10 22:40:29 +01:00
Rafael Fontenelle
cecf778381 Update Brazilian Portuguese translation 2022-01-07 22:59:34 +00:00
Kukuh Syafaat
0663a989f4 Update Indonesian translation 2022-01-05 03:24:29 +00:00
Asier Sarasua Garmendia
7b2d9d0b73 Update Basque translation 2021-12-25 14:00:09 +00:00
Aurimas Černius
f220e11bce Updated Lithuanian translation 2021-12-14 13:49:10 +02:00
Aleksandr Melman
af4165d3e5 Update Russian translation 2021-12-13 11:27:53 +00:00
Sveinn í Felli
c82ca68c03 Update Icelandic translation 2021-12-13 09:08:27 +00:00
Florian Müllner
02e5029eb6 window-list: Fix OSK
The reveal animation moved from Main.layoutManager.keyboardBox to
the keyboard itself, so instead of applying an additional translation
for the bottom panel, we override the translation that would reveal
the keyboard (and thus prevent it from showing altogether).

Fix this by moving our translation to the keyboardBox instead.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/199>
2021-11-26 20:01:40 +01:00
Daniel Mustieles
d98153ba9e Updated Spanish translation 2021-11-26 18:05:13 +01:00
Fran Dieguez
4d913adcec Update Galician translation 2021-11-19 22:22:52 +00:00
MohammadSaleh Kamyab
5729d0b84a Update Persian translation 2021-11-18 22:40:00 +00:00
Sebastian Keller
4a26cecd7d native-window-placement: Remove custom styling
The window-picker padding was causing it to become smaller in the
overview resulting in a jump when opening it and caused sizing issues
with the workspace view in the app picker. However it is not needed
anymore with the new overview, so this can be fixed by simply removing
it.

The horizontal- and vertical-spacing properties got replaced with a
spacing property a while ago. However this is only used in
WorkspaceLayout::_createBestLayout() which gets overridden by this
extension which does not use it. So they can simply be removed.

The shell-caption-spacing property got removed when the window captions
got changed to always use the full length and has not been doing
anything since.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/301
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/309
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/189>
2021-11-17 12:37:28 +00:00
Jordi Mas i Hernandez
e5a3fa4cfa Update Catalan translation 2021-11-15 07:57:14 +00:00
Goran Vidović
6268e82f35 Update Croatian translation 2021-11-12 11:25:34 +00:00
Yaron Shahrabani
348a5777d3 Update Hebrew translation 2021-11-11 22:54:01 +00:00
Hugo Carvalho
594af0c412 Update Portuguese translation 2021-11-07 22:32:42 +00:00
Quentin PAGÈS
d6a81150b6 Update Occitan translation 2021-11-07 19:54:26 +00:00
Fabio Tomat
38b3413e94 Update Friulian translation 2021-11-07 16:51:51 +00:00
Just Perfection
762ec75601 user-theme: Extensions review guidelines compatibility
Extensions review guidelines enforces extensions to
don't create objects in the constructor of the class
that init() returns. so creating settings object in enable()
can make the extension compatible with the ego review guidelines.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/197>
2021-11-06 21:58:59 +00:00
Yuri Chornoivan
6da9a39959 Update Ukrainian translation 2021-11-06 16:35:25 +00:00
Piotr Drąg
2938a1a312 Update POTFILES.in
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/198>
2021-11-06 15:02:17 +01:00
Neal Gompa
eb517c8517 classic: Install the session for Wayland and ship override sessions
The regular GNOME session ships with three options:

* GNOME
* GNOME on Wayland (available when GDM starts in X11)
* GNOME on Xorg (available when GDM starts in Wayland)

The main GNOME session is set up so it works to match how GDM starts,
so GNOME is on Wayland if GDM is (or GNOME is on X11 if GDM is).

For GNOME Classic, we are missing this setup, so port this behavior
over from the GNOME session setup.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/195>
2021-10-29 10:00:02 -04:00
Neal Gompa
a79d2afb2d classic: Add X-GNOME-SessionRegisters
GDM has supported sessions registering with it for a few years now so
it can know when to shut down the greeter. Having the GNOME Classic
session declare that it will register itself allows GDM to avoid
executing a fallback codepath.

This has been supported with the regular GNOME session for a while,
and this session was likely forgotten about when it was added there.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/195>
2021-10-29 09:58:38 -04:00
Sveinn í Felli
396f4ef566 Update Icelandic translation 2021-09-29 10:18:03 +00:00
Goran Vidović
c26b4803c3 Update Croatian translation 2021-09-23 14:38:14 +00:00
Florian Müllner
4ccf12e988 Bump version to 41.0
Update NEWS.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/192>
2021-09-19 12:47:07 +02:00
Florian Müllner
74121fce78 Bump version to 41.rc.1
Update NEWS.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/191>
2021-09-06 01:40:31 +02:00
Florian Müllner
0a7491d747 build: Bump meson requirement
Passing arguments to dist scripts was only introduced after 0.44,
so bump the requirement to shut up the corresponding warning.

Meson 0.53 is the same version requirement as gnome-shell, so that
shouldn't be an issue for distributors.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/191>
2021-09-06 01:40:11 +02:00
Florian Müllner
68bf3e7ff7 ci: Fix classic build
The option name used in CI was wrong, so we did not actually build
the auxiliary classic mode file.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/190>
2021-09-06 00:41:04 +02:00
Florian Müllner
93dd8f535d ci: Init submodule
As the gnome-shell-sass submodule isn't included under subprojects,
meson doesn't handle it automatically.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/190>
2021-09-06 00:39:50 +02:00
Florian Müllner
0b993525f5 build: Check sassc errors when generating stylesheet
We currently just call sassc, but don't check its return value. That
means as long as sassc is available, the script (and therefore the
newly added dist CI job) will succeed.

Make sure we fail on failure.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/190>
2021-09-06 00:33:08 +02:00
Florian Müllner
5dfdb68c75 Bump version to 41.rc
Update NEWS.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/188>
2021-09-05 02:02:52 +02:00
Florian Müllner
443d1dc42b ci: Add dist job
So far, releases are done locally by invoking `meson dist`.

We can do better and leverage the existing CI infrastructure, to get
to the following release workflow:

 - bump version in meson.build, update NEWS etc.
 - open merge request for the release
 - merge when the pipeline (including dist check) succeeds
 - tag the release
 - wait for the tag pipeline to spit out the tarball artifact

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/186>
2021-09-04 05:10:23 +02:00
Florian Müllner
34f6c9514a ci: Add a fedora build job
We currently use a setup modelled after the flatpak CI workflow,
where we produce extension bundles and expose them as artifacts
for easy testing.

It still makes sense to test a regular build though, in particular
as that can include classic mode support.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/186>
2021-09-04 05:10:23 +02:00
Florian Müllner
2f2619403a ci: Build custom image
The gnome-shell image we are using is well-suited for the jobs we
are running, but the lack of sassc means that we don't cover classic
mode.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/186>
2021-09-04 05:10:23 +02:00
Florian Müllner
d25cc847f3 ci: Reindent yaml configuration
The file currently uses a mix of 4 and 2 space indentation (with the
occasional 1 space thrown in). It looks like most GNOME projects have
settled on 2-space indentation, so use that.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/186>
2021-09-04 05:10:23 +02:00
Florian Müllner
769ad859e6 build: Check NEWS for version
I don't think this ever happened to me, but it can't hurt enforcing
that every release has a corresponding NEWS entry.

(The script has been copied from Polari, thus the metainfo support)

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/186>
2021-09-04 05:10:23 +02:00
Florian Müllner
7ba0e5b42c apps-menu: Stop using panel-main-menu shortcut
It's an old GNOME 2 shortcut that's no longer worth supporting in
the regular session. Instead, set up a new shortcut backed by our
own schema.

https://discourse.gnome.org/t/difference-between-show-the-overview-and-show-the-activities-overview-keyboard-shortcuts/6572

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/173>
2021-08-31 23:42:23 +02:00
Florian Müllner
201339345d window-list: Only show at the end of the overview transition
gnome-shell now considers the work area in the overview, so popping
up at the beginning of the overview transition is now more jarring
than at the end.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/185>
2021-08-26 23:36:53 +02:00
Florian Müllner
6ee4205f1e window-list: Fix initial visibility
Mutter uses an undefined initial in-fullscreen state, so it will
always emit the `in-fullscreen-changed` signal when it determines
the actual initial state.

This didn't use to be an issue when the shell started in the session,
but now results in the window list ending up visible in the overview
on startup.

Work around this by hiding ourselves again when the in-fullscreen
state changes in the overview.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/185>
2021-08-26 23:28:44 +02:00
Florian Müllner
2307e2cabe Bump version to 41.beta
Update NEWS.
2021-08-18 01:50:19 +02:00
Florian Müllner
4becaa28ce Update sass submodule 2021-08-18 01:50:19 +02:00
Florian Müllner
cc45bd63ab cleanup: Use new gettext() convenience
gnome-shell now includes convenience helpers for gettext functions that
use an extension's text domain (as initialized by initTranslations()).

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/183>
2021-08-14 23:15:56 +02:00
Florian Müllner
757bcee4e2 build: Use backend-agnostic meson commands for export
There's no alternative backend in sight for us, but it's nice to
only deal with a single build tool.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/182>
2021-08-13 05:25:47 +02:00
Florian Müllner
1340b209f9 window-list: Simplify radio handling
Instead of handling the active state manually and updating settings
on changes, we can use GActions to leave the nitty-gritty to GTK.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/181>
2021-08-13 05:22:41 +02:00
Florian Müllner
8f362d57fe lint: Synchronize configuration with gjs
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/180>
2021-08-13 04:57:35 +02:00
Florian Müllner
d0b9c9b54a cleanup: Document functions
gjs now enforces this in its eslint configuration. Adding type
information generally is a good idea, so add appropriate comments
to public functions before picking up that configuration change.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/180>
2021-08-13 04:48:22 +02:00
Florian Müllner
6284b0c489 window-list: Move functions into base class
The helper functions date back to a time when AppButton and WindowButton
were unconnected classes. But nowadays they share a common base class, so
we have a better place for them than external helper functions.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/180>
2021-08-13 04:39:00 +02:00
Florian Müllner
8a211f98fd build: Rewrite gettext domain when exporting zips
Now that every extension picks up its gettext domain from
its metadata, we can easily change it when exporting the
zips.

That ensures that every extension only binds its own domain
instead of messing up other extension's translations.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/335

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/179>
2021-08-11 19:05:45 +02:00
Florian Müllner
d6633397b7 build: Remove unused variable
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/335

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/179>
2021-08-11 19:05:45 +02:00
Florian Müllner
0d06cc685e extensions: Pick up gettext domain from metadata
Since commit a6ee142f21, the extension archives that are uploaded
to extensions.gnome.org only contain strings that are relevant for
the extension, not all translations from all extensions.

Unfortunately all extensions still share a common gettext domain,
so the extension with the last bind_textdomain() call wins and
leaves the others without translations.

We'll address this by using distinct domains when not installed
system-wide. That becomes easier if there is a canonical place
for the text domain, with the existing metadata key being the
natural choice.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/335

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/179>
2021-08-11 18:42:43 +02:00
Marco Trevisan (Treviño)
8de89a44a4 README: Fix typo on instructions to move to main branch 2021-07-21 19:50:34 +02:00
Florian Müllner
f3b1f10f6c ci: Set FDO_UPSTREAM_REPO
ci-fairy uses the variable to set the upstream remote that is used
to build the commit range to check.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/178>
2021-07-19 17:23:44 +02:00
Florian Müllner
2bced47762 classic: Remove padding from app menu
It is now inconsistent with other top bar items, so drop it.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/167>
2021-07-18 21:57:38 +00:00
Florian Müllner
7ba9b87064 docs: Add README section for default branch
We are about to change it, so briefly outline how to update local
checkouts.

(Copied from glib)

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/177>
2021-07-14 21:11:59 +02:00
Florian Müllner
a642c439ce docs: Use HEAD in external URLs
That way the link will keep working when the other project changes
its default branch name.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/177>
2021-07-14 20:37:15 +02:00
Florian Müllner
d421bbfa60 drive-menu: Hide items initially
Now that the check for network mounts is non-blocking, the initial
sync doesn't take effect immediately. We don't want hidden items
to briefly flash the indicator, so create them initially hidden.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/176>
2021-07-13 11:54:21 +02:00
Florian Müllner
3539ce1139 drive-menu: Fix indicator visibility
Commit 519269be9d made the check for network mounts non-blocking, and
we now update the indicator's visibility before a newly-added network
mount is hidden.

Address this by monitoring the item itself for visibility changes.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/176>
2021-07-13 11:46:16 +02:00
Florian Müllner
94b907f46d window-list: Init translations
Whoops, we are missing the bindtextdomain() call, which means translations
won't work when no other extension that shares the same domain is used
(like in GNOME Classic for instance).

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/340

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/174>
2021-07-12 16:04:50 +00:00
Alexander Shopov
1e04622eb4 Update Bulgarian translation 2021-07-11 08:21:24 +00:00
Florian Müllner
519269be9d drive-menu: Avoid blocking I/O when querying filesystem
The last commit improved the heuristics for detecting network mounts,
but at the price of potentially blocking the shell. Avoid that drawback
by making the code in question async.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/53

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/27>
2021-06-23 18:15:42 +02:00
Florian Müllner
7d6670ce3c drive-menu: Don't assume mounts without volume are local
The intention of the code is to only expose actually plugged in
devices rather than network mounts, but the existing heuristics are
based on GVolume and simply assume a local mount where there's no
associated volume. Fill that gap by querying the ::remote filesystem
attribute in that case.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/53

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/27>
2021-06-23 17:52:19 +02:00
Juliano de Souza Camargo
50bd597baa Update Portuguese translation
(cherry picked from commit 12eedcf6f7)
2021-06-07 10:22:07 +00:00
Hugo Carvalho
4403b54fbc Update Portuguese translation
(cherry picked from commit 08d382facc)
2021-06-02 16:10:00 +00:00
Adam Goode
d6648b0b5c window-list: Don't use panel-button class for the workspace indicator
The panel-button introduces some horizontal padding which is insensitive
to scroll events. Without this change, there is a small dead zone in the
corner that cannot be used to switch workspaces with the mouse wheel.

For useMenu mode, this has the effect of removing all of the horizontal
space to the edge of the screen, so I add some back with the
status-label-bin margin.

This a is similar change to 8bad8a3b63.

Fixes #315.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/171>
2021-05-26 11:57:41 +00:00
Florian Müllner
861e5c0be6 build: Only use major version in shell-versions
The website changed its version handling again, and now takes "40.0"
to mean "40.0, and only 40.0".

Not complaining though, as "40" is more correct in my opinion anyway ...

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/172>
2021-05-25 15:45:21 +02:00
Florian Müllner
bf86b84d6c Post-release version bump 2021-05-14 17:01:12 +02:00
Florian Müllner
605dd02217 Tag release 40.1
Update NEWS.
2021-05-13 16:51:52 +02:00
Florian Müllner
b33a62f2dc Update sass submodule 2021-05-13 16:50:34 +02:00
Quentin PAGÈS
8a320eb0a1 Update Occitan translation 2021-05-10 20:04:48 +00:00
Pawan Chitrakar
83c4ced407 Update Nepali translation 2021-05-01 05:49:03 +00:00
Florian Müllner
e094dead91 windowsNavigator: Adjust to gnome-shell change
Parts of WindowPreview were moved to C for performance reasons, which
turned a formerly private JS property into a GObject property.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/302

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/170>
2021-04-08 16:38:40 +02:00
Carmen Bianca BAKKER
6cdf86b6b3 Update Esperanto translation 2021-04-07 12:05:20 +00:00
Florian Müllner
3e8bbb07ea classic: Disable welcome dialog
The Tour focuses on new overview features, which aren't relevant
for gnome-classic where the overview is disabled altogether.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4026

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/169>
2021-04-05 20:32:19 +02:00
Anders Jonsson
e3ddd8e7d0 Update Swedish translation 2021-03-27 20:14:29 +00:00
Ngọc Quân Trần
aa67982129 Update Vietnamese translation 2021-03-27 07:54:17 +00:00
Florian Müllner
8aa645ae5d build: Adjust shell-version
With the new version scheme, only the major version is relevant as
far as gnome-shell is concerned. However the extension website does
not handle that at the moment, so always append a ".0".
2021-03-20 13:39:25 +01:00
Florian Müllner
20540cb843 Post-release version bump 2021-03-20 13:39:25 +01:00
Florian Müllner
d338930d69 Tag release 40.0
Update NEWS.
2021-03-20 13:10:47 +01:00
Jiri Grönroos
35c1763792 Update Finnish translation 2021-03-16 10:15:46 +00:00
Florian Müllner
7a87bdcb1b Post-release version bump 2021-03-16 00:00:31 +01:00
Florian Müllner
50b6bd1884 Tag release 40.rc
Update NEWS.
2021-03-15 16:32:30 +01:00
Florian Müllner
db853d9023 Update sass submodule 2021-03-15 16:29:55 +01:00
Florian Müllner
5be44705f7 window-list: Improve preview styling
The current styling doesn't indicate the active workspace very well, and
makes it difficult to differentiate empty workspaces from workspaces with
maximized windows.

Tweak the styling to address those issues.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/283

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/166>
2021-03-11 12:08:38 +00:00
Florian Müllner
fdfa46099b workspace-indicator: Improve preview styling
The current styling doesn't indicate the active workspace very well, and
makes it difficult to differentiate empty workspaces from workspaces with
maximized windows.

Tweak the styling to address those issues.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/283

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/166>
2021-03-11 12:08:38 +00:00
Florian Müllner
f987e5f13d workspace-indicator: Reindent stylesheet
For some reason the CSS here uses a different indentation than
gnome-shell or the other extensions, fix that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/283

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/166>
2021-03-11 12:08:38 +00:00
Florian Müllner
c766230118 window-list: Only show previews for up to six workspaces
On request of GNOME Classic users, we add GNOME2-like workspace previews
when using a horizontal workspace layout. The previews scale a lot worse
than the menu though, with the risk that they take up all the available
width in extreme cases.

Address this by also taking the number of workspaces into account, and
switch to the menu when we have more than six.

This is particularly important now that we switched to a horizontal
layout by default.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/165>
2021-03-10 20:11:18 +01:00
Florian Müllner
bb2b1204b4 workspace-indicator: Only show previews for up to six workspaces
On request of GNOME Classic users, we add GNOME2-like workspace previews
when using a horizontal workspace layout. The previews scale a lot worse
than the menu though, with the risk that they take up all the available
width in extreme cases.

Address this by also taking the number of workspaces into account, and
switch to the menu when we have more than six.

This is particularly important now that we switched to a horizontal
layout by default.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/165>
2021-03-10 20:11:18 +01:00
Florian Müllner
cf3690a434 windowsNavigator: Adjust to gnome-shell changes
Unsurprisingly, the big overview changes in gnome-shell broke the
extension. Make the necessary adjustments to get it working again:
 - changed constructor parameters for Workspace/WorkspacesView
 - overall state handling done by adjustment
 - window preview layout changes

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/296

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/163>
2021-03-10 15:28:37 +00:00
Florian Müllner
7062acf10f native-window-placement: Adjust to gnome-shell changes
More unsurprising breakage:
 - the workspace layout/strategy relation has been cleaned up
 - window previews now include an icon that influences the
   title position
 - window previews scale up on hover, which again influences
   the title position

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/164>
2021-03-10 15:26:26 +00:00
Fran Dieguez
7ace9c4d51 Update Galician translation 2021-02-24 21:14:57 +00:00
Florian Müllner
23887ce2a3 Post-release version bump 2021-02-24 01:57:00 +01:00
Florian Müllner
e8b8677bfe Tag release 40.beta
Update NEWS.
2021-02-24 01:50:31 +01:00
Florian Müllner
3603bc7c6a Update sass submodule 2021-02-24 01:50:31 +01:00
Florian Müllner
1e44941db6 drive-menu: Remove unused style class
The .single-indicator class was added to add extra spacing to
lone top bar items when removing the arrows, but dropped again
after solving the extra spacing differently.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/161>
2021-02-24 00:45:58 +00:00
Florian Müllner
f71da9e843 window-list: Replace WorkspaceBackground as well
The shell now scales down the backgrounds and adds a rounded corner
clip. Undo both those changes with another override.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/160>
2021-02-24 01:24:11 +01:00
Florian Müllner
1b4a20a8af window-list: Replace Workspace prototype
This is arguably more elegant than injecting into individual methods, and
will be consistent with an upcoming override that cannot be implemented
as method injection.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/160>
2021-02-24 01:24:11 +01:00
Florian Müllner
d8e179ed09 window-list: Adjust to OSK changes
Visibility changes are now handled internally, without an easy way
for us to hook into. We can resort to a hack though, as the gesture
action to bring up the keyboard is only enabled while the keyboard
is hidden.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/160>
2021-02-24 01:24:11 +01:00
A S Alam
8016cf7ae9 Update Punjabi translation 2021-02-14 00:58:36 +00:00
Аляксей
7774426eb9 Update Belarusian translation 2021-02-12 16:18:20 +00:00
Florian Müllner
9fa522c29a window-list: Adjust to overview changes
The overview code changed significantly, including the bits we re-use
to implement the window picker in the classic session. Adjust to those
changes to unbreak the extension.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/159>
2021-02-12 02:20:20 +01:00
Florian Müllner
b92295ad2c Update sass submodule
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/159>
2021-02-12 02:20:20 +01:00
Florian Müllner
d7c8a5d193 extensions: Remove horizontal-workspaces extension
Workspaces are now horizontal by default, so we don't need to change
the layout for classic mode anymore.

That was the only reason why the extension was added, so it has now
outlived its usefulness.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/158>
2021-01-29 16:09:59 +00:00
Michael Lawton
0d8d6dceb0 places-menu: Mark mounts that can be unmounted as removable
While the eject() code falls back to unmount() for mounts that
don't support ejecting, it's not possible to actually do so
because we hide the eject button.

Fix this by treating all mounts as removable that can either be
ejected or unmounted.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/161

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/152>
2021-01-28 12:25:26 +01:00
Daniel van Vugt
8a5e793b3d auto-move-windows: Don't move windows already on all workspaces
This fixes a particular case of mutter#992.

Although gnome-shell will also be softened to not crash in future, it's
also a good idea for the extension to explicitly decide how it wants to
handle windows that are already on all workspaces.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/157>
2021-01-28 16:33:50 +08:00
Florian Müllner
8fcbed6481 classic: Remove arrow-override
No need to hide what is no longer there.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3567

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/156>
2021-01-26 17:00:24 +01:00
Florian Müllner
ac2ed286e1 extensions: Remove arrows from top bar menus
... following the corresponding gnome-shell change.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3567

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/156>
2021-01-26 16:59:43 +01:00
Florian Müllner
3c3c1f702d window-list: Add tooltips to workspace thumbnails
When showing previews instead of the menu, the workspace names
don't appear anywhere. Some users care strongly about those, so
expose them as tooltip on hover.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/155>
2021-01-20 23:58:13 +01:00
Florian Müllner
c33be29f56 workspace-indicator: Add tooltips to workspace thumbnails
When showing previews instead of the menu, the workspace names from
our preferences don't appear anywhere. Some users care strongly about
those, so expose them as tooltip on hover.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/155>
2021-01-20 23:58:13 +01:00
Florian Müllner
d8ae2dcba2 window-list: Drop height override
gnome-shell's top bar got taller, and is now just 1px smaller than
our size override. We don't need that additional pixel to fit our
UI, so remove the override to make the sizes of both bars consistent.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/271

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/154>
2021-01-18 22:43:52 +01:00
Florian Müllner
3b14c0a04e Post-release version bump 2021-01-14 19:04:45 +01:00
Florian Müllner
0e3d6465eb Tag release 40.alpha.1
Update NEWS.
2021-01-14 19:02:07 +01:00
Florian Müllner
d381a0b89b auto-move-windows: Use Gtk.Button.icon_name property
Image buttons are a very common pattern, so GTK4 added some
convenience API we can use to construct them.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
5df0fa145b workspace-indicator: Use Gtk.Button.icon_name property
Image buttons are a very common pattern, so GTK4 added some
convenience API we can use to construct them.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
f0ff0e1400 workspace-indicator: Stop using header func for separators
GTK4 added built-in support for this common pattern, so use that
instead.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
53f5a92dc8 user-theme: Stop using header func for separators
GTK4 provides built-in support for this common pattern, so use
that instead.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
d5c31273ee auto-move-windows: Stop using header func for separators
GTK4 added built-in support for this common pattern, so use that
instead.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
22ea58a849 workspace-indicator: Port to GTK4
With this port, all extensions now use GTK4 for their preferences.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
67d96993ce auto-move-windows: Port to GTK4
Just like the previous ports, this consists mostly of
replacing the old Gtk.Container methods.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
96dd4f9835 window-list: Port to GTK4
Another easy port:
 - replace Gtk.Container methods
 - stop using show_all()
 - Gtk.CheckButton now provides the
   Gtk.RadioButton functionality as well

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
3bef6be7c1 user-theme: Port to GTK4
With the previous preparations in place, the actual GTK4 port is
now trivial:
 - replace Gtk.Container methods with widget-specific methods
 - stop using show_all()

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:55 +01:00
Florian Müllner
b83d38a72e user-theme: Track GSettings to sync checkmark
GTK4 removes the generic GtkWidget API for accessing an inserted
action group, so we need an alternative for tracking the currently
selected theme.

Using the underlying GSettings object looks like the easiest option,
so do that.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:54 +01:00
Florian Müllner
5b73960f34 extensions: Stop using :margin shortcut
The property has been removed in GTK4, so prepare for a port by
setting the four individual margin properties instead.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/148>
2021-01-14 14:40:54 +01:00
Jonas Dreßler
505a7f4ac9 classic: Fixup panel styling after gnome-shell changes
We don't want a transparent panel in the classic session (this is
already taken care of by the existing panel background-color overrides),
and we want to avoid the new pill-shaped hover/focus indicators in the
classic session.

For the gnome-shell changes, see
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1397.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/153>
2021-01-14 00:25:47 +01:00
Florian Müllner
e8acfb2b51 Update sass submodule
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/153>
2021-01-14 00:25:47 +01:00
Florian Müllner
dcd5dc4c7f ci: Add back commit-rules file
Somehow git-mv ended up as git-rm without me noticing, whoops.
2021-01-11 14:17:04 +01:00
Florian Müllner
2702cdf889 ci: Update ci-fairy image
The default rules file name has changed from commitrules.yml to
commit-rules.yml, adjust to that change.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/151>
2021-01-11 14:03:44 +01:00
Florian Müllner
669e7c32a2 classic: Pre-generate stylesheet
We follow the rule of not putting generated files under version
control, but that means drawing in additional build-time dependencies.
We can reduce those when building from a released tarball by
generating the stylesheets at dist time though, so do that.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/150>
2020-12-29 00:27:07 +01:00
Florian Müllner
294eb0feb5 data: Update list of theme dependencies
The scss sources were split up in gnome-shell last cycle, catch
up with that change.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/150>
2020-12-29 00:16:16 +01:00
Florian Müllner
a7ddbd0d53 Change upcoming version (again)
The extension website doesn't handle the chosen scheme correctly,
so use 40.alpha.1 instead.
2020-12-25 23:29:06 +01:00
Florian Müllner
c745dd6362 build: Change upcoming version to 40.alpha2
I messed up and released 40.alpha at the same time as 3.38.2, when it's
supposed to be in January. In order to re-align with the schedule, change
the upcoming version to 40.alpha2 so we don't have to skip a release and
will be back on track in time of 40.beta.
2020-12-22 01:33:44 +01:00
Florian Müllner
a4cf9f956e ci: Add some more commit message rules
Now that we have the ability to easily define custom rules, add some
more to enforce the existing commit message style.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/149>
2020-12-18 19:26:50 +01:00
Florian Müllner
02aa68b24a ci: Replace custom commit-log script with ci-fairy
ci-fairy now supports checking commit messages for required/disallowed
patterns. Use that to replace our custom commit-log script.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/149>
2020-12-18 19:26:42 +01:00
Florian Müllner
4e731e1dce Post-release version bump 2020-12-02 20:40:19 +01:00
Florian Müllner
eee341e907 Tag release 40.alpha
Update NEWS.
2020-12-02 20:33:56 +01:00
Florian Müllner
aad96bb1c4 Update sass submodule 2020-12-02 20:33:56 +01:00
Florian Müllner
50d3ee5703 workspace-indicator: Use overlap to determine preview visibility
In order to better reflect the actual workspace, show any preview
that is at least partially located on the monitor, not only those
that have the major part on that monitor.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/142>
2020-12-02 19:27:44 +01:00
Florian Müllner
08dfb78815 window-list: Use overlap to determine preview visibility
In order to better reflect the actual workspace, show any preview
that is at least partially located on the monitor, not only those
that have the major part on that monitor.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/142>
2020-12-02 19:22:51 +01:00
Florian Müllner
6949a5d075 workspace-indicator: Account for monitor offset in window previews
Windows' frame rects are in screen coordinates, while the workspace
thumbnails are based on the monitor work area. Unless we account
for the difference, previews end up mispositioned in multi-monitor
setups.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/142>
2020-12-02 19:22:12 +01:00
Florian Müllner
893d3b0473 window-list: Account for monitor offset in window previews
Windows' frame rects are in screen coordinates, while the workspace
thumbnails are based on the monitor work area. Unless we account
for the difference, previews end up mispositioned in multi-monitor
setups.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/142>
2020-12-02 19:20:08 +01:00
Florian Müllner
f5128e13f2 workspace-indicator: Round calculated preview sizes
While not strictly necessary, there's no reason to differ from the
copy in the window-list extension ...

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/142>
2020-12-02 19:17:36 +01:00
Ray Strode
8318ea919f window-list: Stop monitoring drag operation if window list is destroyed
If a user is in the middle of a drag in the window list and the
window list associated with the drag gets destroyed, the drag
monitor gets leaked.

Later when the drag motion is processed, spew goes to the log:

clutter_actor_contains: assertion 'CLUTTER_IS_ACTOR (self)' failed

Examples of triggers for this bug:

- The monitor topology changes
- The screen gets locked during the drag

This commit fixes the spew and the leak by ensuring any pending
drag monitoring is disabled when the window lists are destroyed.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/145>
2020-11-25 17:48:21 +00:00
Florian Müllner
bde20e78f0 ci: Bump ci-fairy template include
This fixes the check-merge-request job when MR branch and target branch are
on the same repo.

See
https://gitlab.freedesktop.org/freedesktop/ci-templates/-/merge_requests/66

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/146>
2020-11-24 16:28:40 +01:00
Jordan Petridis
02db9525e7 ci: Replace only/except with rules
only/except keywords where deperecated in favor of rules.

Since we started using GNOME/gnome-shell!1492 it introduced
a second pipeline being run for each commit.

Detached pipelines are the only way to access CI_MERGE_REQUEST_*
variables, and if we disable normal pipelines you will need to
create wip/spam MRs in order to run the tests.

This reworked rules makes it so, the normal pipeline needs manual
interaction to be started, and the detached/MR pipleines is always
run.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/144>
2020-11-21 01:14:39 +01:00
Jordan Petridis
8d4586bd57 ci: Set some sensible defaults
* Allow for all jobs to be cancelled if a newer commit is pushed
* Automatically retry jobs if they fail due to some infrastructure issue

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/144>
2020-11-21 01:14:39 +01:00
Jonas Ådahl
8872659621 ci: Check that merge requests have the right settings
This will catch the missing "allow write access for maintainers" check
box being checked.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/144>
2020-11-21 01:14:39 +01:00
Florian Müllner
46c7677643 ci: Use ci-fairy image for commit log check
This is in line with what mutter/gnome-shell are using, and should
be smaller (read: faster) than the gjs image.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/144>
2020-11-21 01:14:39 +01:00
Jonas Ådahl
4b9f4b1b63 doap: Make marge-bot a maintainer
This is so that the merge button can be restricted to maintainers, thus
decreasing the risk of merging using the merge button.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/141>
2020-11-19 01:32:23 +01:00
Jonas Ådahl
b64c93897b ci: Wait for 'check-commit-log' before continuing
The check-commit-log is quick, and to get a result early is helpful as
one can then more quickly check for failures via the report provided via
the JUnit report.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/141>
2020-11-19 01:32:23 +01:00
Jonas Ådahl
a7939f18d1 ci/check-commit-log: Generate JUnit report
This means the merge request will see the commit log review issues
causing the pipeline to fail without having to dig through CI log files.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/141>
2020-11-19 01:13:11 +01:00
Jonas Ådahl
15efbc29be ci/check-commit-log: Reverse the merge request URL check
Instead of making sure there is a reference to a bug or merge request,
make sure there isn't. The reason for this is that marge-bot will always
append a merge request URL in the end of the commit message.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/141>
2020-11-19 01:13:11 +01:00
Florian Müllner
6e5466a4ec ci: Explicitly specify job dependencies
We can speed up CI a bit by allowing build jobs to run in parallel
with review jobs.

See https://gitlab.gnome.org/help/ci/yaml/README.md#needs for details.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/141>
2020-11-19 01:12:29 +01:00
Thun Pin
737c897624 window-navigator: Adjust to 3.38 overview changes
gnome-shell's overview code changed significantly in 3.38,
adjust the extension to work without the separate overlay.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/259
2020-11-18 23:54:18 +00:00
Florian Müllner
c317a876dd ci: Switch to updated gnome-shell image
gnome-shell now produces a CI image as part of its pipeline. Use that
instead of the old, manually-updated image.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/140
2020-11-19 00:22:01 +01:00
Florian Müllner
72c67aacc4 lint: Sync configuration with gjs
gjs updated its eslint configuration, so sync our copy.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/137
2020-11-14 00:58:52 +01:00
Florian Müllner
ba7e3fc0b5 cleanup: Remove empty leading/trailing lines in blocks
gjs added a new rule to its eslint ruleset that forbids "block padding",
so make sure we conform to that rule before syncing up the configuration.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/137
2020-11-14 00:58:52 +01:00
Florian Müllner
61cf679b8c auto-move-windows: Exclude sticky windows from empty-check
We modify gnome-shell's workspace tracker to only remove empty
workspaces from the end. However we currently don't take into
account that sticky windows appear on all workspaces, so those
are preventing any workspace from getting removed at the moment.

Exclude them when determining whether a workspace is empty to
get the expected behavior.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/135
2020-11-13 23:53:49 +00:00
Florian Müllner
ba55bacab4 ci: Use junit output format
Gitlab has built-in support for junit reports, so switch eslint's
output to that format.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/136
2020-11-07 01:55:02 +01:00
Jordi Mas
9445bd2205 Update Catalan translation 2020-10-23 21:10:23 +02:00
Florian Müllner
6ed1f45ffd window-list: Use custom layout manager for thumbnails
The current code positions window previews explicitly using a fixed
layout manager. For that it relies on a valid parent allocation,
which is error-prone and frequently results in warnings.

Address this by moving the positioning code into a custom layout
manager, and only update the visibility from the window preview.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/260
2020-10-21 03:09:45 +02:00
Florian Müllner
81be1d2e2f workspace-indicator: Use custom layout manager for thumbnails
The current code positions window previews explicitly using a fixed
layout manager. For that it relies on a valid parent allocation,
which is error-prone and frequently results in warnings.

Address this by moving the positioning code into a custom layout
manager, and only update the visibility from the window preview.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/260
2020-10-21 03:09:40 +02:00
Florian Müllner
52abf74088 window-list: Adjust to overview changes
Window DND in the overview is now based on the metaWindow,
not the window actor (misnamed as "real window").

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/133
2020-10-21 01:05:07 +00:00
Florian Müllner
623bc6dbf3 workspace-indicator: Adjust to overview changes
Window DND in the overview is now based on the metaWindow,
not the window actor (misnamed as "real window").

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/133
2020-10-21 01:05:07 +00:00
Fabio Tomat
04b23ec68f Update Friulian translation 2020-10-17 20:14:41 +00:00
Sergio Costas
b65f362f0d window-list: Honor changes in skip-taskbar property
Although window-list checks the 'skip-taskbar' property when a
window is added to the desktop to decide wether it should be
shown in the bar or not, it doesn't honor that when the property
is changed after a window has already been added. Since the new
WaylandClient API allows to change this property for already
mapped windows, supporting this is a good idea.

This patch fixes this.

Fix https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/130
2020-10-08 23:42:21 +02:00
Florian Müllner
7c30f35b12 Bump version to 40.alpha
The GNOME project has adopted a new versioning scheme[0], and
GNOME 3.38 will be followed by GNOME 40.

Open the new development cycle by switching to the new scheme, as
well as to post-release bumps as recommended.

[0] https://discourse.gnome.org/t/new-gnome-versioning-scheme/4235

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/131
2020-10-06 15:07:54 +02:00
Florian Müllner
9e976f06b4 Bump version to 3.38.1
Update NEWS.
2020-10-05 20:43:21 +02:00
Florian Müllner
369801dbeb Update sass submodule 2020-10-05 20:42:16 +02:00
Yosef Or Boczko
2c3c7e8a73 Update Hebrew translation 2020-09-28 19:05:19 +00:00
Stas Solovey
bb8f34de83 Update Russian translation 2020-09-22 19:52:00 +00:00
Cheng-Chia Tseng
6c98658fe1 Update Chinese (Taiwan) translation 2020-09-22 15:07:44 +00:00
Yacine Bouklif
3f06c2bc04 Add Kabyle translation 2020-09-19 11:51:36 +00:00
Florian Müllner
9e38b091a9 Bump version to 3.38.0
Update NEWS.
2020-09-14 22:52:43 +02:00
Rūdolfs Mazurs
62d7b883f0 Update Latvian translation 2020-09-12 09:06:28 +00:00
Milo Casagrande
e56a9c5681 Update Italian translation 2020-09-10 08:12:04 +00:00
Tim Sabsch
03aa180472 Update German translation 2020-09-09 06:04:41 +00:00
Juliano Camargo
bbb0775e1a Update Portuguese translation 2020-09-08 20:08:29 +00:00
Alan Mortensen
c41d285131 Updated Danish translation 2020-09-07 19:58:09 +02:00
Balázs Meskó
cc63876b7e Update Hungarian translation 2020-09-06 21:06:21 +00:00
Florian Müllner
08769ec0b6 Bump version to 3.37.92
Update NEWS.
2020-09-06 01:06:49 +02:00
Dušan Kazik
5615c21797 Update Slovak translation 2020-09-02 12:02:31 +00:00
Changwoo Ryu
48d2b4c902 Update Korean translation 2020-08-30 07:46:02 +00:00
Marek Černocký
a43db7233d Updated Czech translation 2020-08-28 22:21:25 +02:00
Aurimas Černius
25143c92f4 Updated Lithuanian translation 2020-08-26 22:34:38 +03:00
Zander Brown
c4ab7e9bbf Update British English translation 2020-08-26 12:25:53 +00:00
Nathan Follens
1d082fc026 Update Dutch translation 2020-08-25 15:38:07 +00:00
Florian Müllner
75919911f5 Bump version to 3.37.91
Update NEWS.
2020-08-24 18:09:27 +02:00
Florian Müllner
bf1f129854 Update sass submodule 2020-08-24 18:07:44 +02:00
Goran Vidović
59bcc0a6a7 Update Croatian translation 2020-08-19 22:39:08 +00:00
Goran Vidović
61a54add2e Update Croatian translation 2020-08-19 22:38:38 +00:00
Марко Костић
17d07239c1 Update Serbian translation 2020-08-19 05:21:54 +00:00
Jiri Grönroos
bf8a31a6c8 Update Finnish translation 2020-08-16 15:17:57 +00:00
Rafael Fontenelle
1d2fdf5c19 Update Brazilian Portuguese translation 2020-08-16 10:30:03 +00:00
Piotr Drąg
f6ada58f5f Update Polish translation 2020-08-15 11:39:47 +02:00
Kukuh Syafaat
ebfbc397be Update Indonesian translation 2020-08-13 12:19:05 +00:00
Akarshan Biswas
02290e8bba Update Bengali (India) translation 2020-08-13 04:36:03 +00:00
Fran Dieguez
1537ac39d4 Update Galician translation 2020-08-12 23:02:45 +00:00
Florian Müllner
e39c3b4561 Bump version to 3.37.90
Update NEWS.
2020-08-11 17:32:17 +02:00
Florian Müllner
80030687d9 Update sass submodule 2020-08-11 17:30:02 +02:00
Alexandre Franke
3859c09318 Update French translation 2020-08-10 10:50:40 +00:00
Asier Sarasua Garmendia
a41cd3c19a Update Basque translation 2020-08-10 07:06:33 +00:00
Anders Jonsson
fcbdeba8c5 Update Swedish translation 2020-08-01 23:10:54 +00:00
Piotr Drąg
116f074e3b Update POTFILES.in
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/128
2020-08-01 14:38:05 +02:00
Florian Müllner
9a78c7e4f4 classic: Drop separate gnome-session definition
Originally the classic session replaced `gnome-shell.desktop` with
`gnome-shell-classic.desktop` (to add the --mode=classic parameter)
and added `nautilus-classic.desktop` (to force on desktop icons).

Neither is the case anymore (and hasn't been for years): Nowadays the
only expected difference is the GNOME_SHELL_SESSION_MODE variable and
the DesktopNames field, which are both set from the session .desktop
file rather than the gnome-session session definition.

Any difference in the latter - like not starting the USBProtection
plugin and missing systemd user session support - are bugs. The
easiest way to avoid those in the future is by removing the obsolete
duplication that enables them, so do just that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/126
2020-07-31 08:52:51 +00:00
Efstathios Iosifidis
9a2d6d68ff Update Greek translation 2020-07-13 21:42:11 +00:00
Fabio Tomat
bc49778100 Update Friulian translation 2020-07-12 16:10:38 +00:00
Florian Müllner
67d2e2f623 Bump version to 3.37.3
Update NEWS.
2020-07-07 18:47:17 +02:00
Florian Müllner
eff625fcb8 native-window-placement: Adjust to gnome-shell changes
The extension was affected pretty badly by the window picker overhaul;
adjust to all(?) the major and minor changes to get it to work again.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/124
2020-07-07 17:39:36 +02:00
Florian Müllner
3742f79d4b window-list: Adjust to gnome-shell changes
The window picker saw a significant overhaul. Amazingly the adjustments
necessary are relatively small ...

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/124
2020-07-07 17:31:52 +02:00
Florian Müllner
b6a3503f5e window-list: Remove some dead code
Since PanelMenu.Button started to inherit from St.Widget, the custom
_allocate() function isn't called anymore.

Simply changing the function to vfunc_allocate() doesn't work as other
changes happened in the meantime, so for now just remove it altogether.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/124
2020-07-07 17:31:52 +02:00
Baurzhan Muftakhidinov
f449ab31c9 Update Kazakh translation 2020-07-02 06:40:14 +00:00
Baurzhan Muftakhidinov
920b925b12 Update Kazakh translation
(cherry picked from commit 9a8b5caca3)
2020-06-25 05:18:54 +00:00
Boyuan Yang
ad5e70b03b Update Chinese (China) translation 2020-06-23 21:15:19 +00:00
sicklylife
7beebc11f6 Update Japanese translation 2020-06-10 12:34:10 +00:00
sicklylife
1391acd71f Update Japanese translation 2020-06-10 12:18:25 +00:00
Jordi Mas
761fdf1036 Update Catalan translation 2020-06-06 14:42:37 +02:00
Florian Müllner
7f2c39cdb2 Bump version to 3.37.2
Update NEWS.
2020-06-02 22:16:25 +02:00
Matej Urbančič
b5ff860118 Updated Slovenian translation 2020-06-01 22:08:36 +02:00
Florian Müllner
aeaba3f379 window-list: Replace removed Clutter.BoxLayout method
The method was deprecated for years and has finally been removed.
Just set appropriate expand/align properties on the children and
add them with the usual add_child() method.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/122
2020-05-28 02:46:06 +02:00
Florian Müllner
f96943a4dc window-list: Replace allocation-changed signal
It has been removed in favor of notify::allocation.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/122
2020-05-28 02:46:06 +02:00
Florian Müllner
60ad2e37ff window-list: Stop using obsolete StBin properties
Those properties were deprecated (and made no-ops) last cycle, and
have now been removed altogether.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/122
2020-05-28 02:46:06 +02:00
Florian Müllner
8c53fd9590 workspace-indicator: Stop using obsolete StBin properties
Those properties were deprecated (and made no-ops) last cycle, and
have now been removed altogether.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/122
2020-05-28 02:46:06 +02:00
Daniel Șerbănescu
867ace0b0a Update Romanian translation 2020-05-22 09:14:46 +00:00
Danial Behzadi
a74862e745 Update Persian translation 2020-05-12 14:27:33 +00:00
Emin Tufan Çetin
c16f9828bd Update Turkish translation 2020-05-05 14:34:53 +00:00
Daniel Mustieles
608a8b1639 Updated Spanish translation 2020-05-04 15:45:54 +02:00
Yuri Chornoivan
7bc9b282a2 Update Ukrainian translation 2020-05-03 19:20:15 +00:00
Florian Müllner
9db7b96f24 window-list: Modernize preference dialog a bit
The current widget uses UI patterns that are reminiscent of GNOME 2.
It doesn't take a lot to make it look more modern: Simply giving the
radio group a distinct background and border allows us to move the
whole UI to the center, making the dialog more balanced and visually
pleasing.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/121
2020-05-03 19:51:24 +02:00
Florian Müllner
c87cfc822a auto-move: Overhaul preference dialog
auto-move uses the same outdated UI pattern as workspace-indicator did
until commit 90d3c5c51d, imposing the same problems for a future GTK4
port.

So replace treeview and toolbar with an editable list like we did for
the other extension.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/121
2020-05-03 19:51:24 +02:00
Cheng-Chia Tseng
ff94c5a143 Update Chinese (Taiwan) translation 2020-05-02 08:06:58 +00:00
Florian Müllner
81f999f761 Bump version to 3.37.1
Update NEWS.
2020-04-29 21:55:52 +02:00
Florian Müllner
17b5c0400a Update sass submodule 2020-04-29 21:49:53 +02:00
Florian Müllner
ac937b9549 user-theme: Make rows non-selectable
A row has to be activated to select a theme, not merely selected.
The selection therefore doesn't do anything, so disable it.
2020-04-29 21:44:13 +02:00
Daniel Mustieles
0c223de045 Updated Spanish translation 2020-04-28 17:47:14 +02:00
Anders Jonsson
564235d44c Update Swedish translation 2020-04-26 18:52:30 +00:00
Yuri Chornoivan
92a2361306 Update Ukrainian translation 2020-04-25 08:07:50 +00:00
Danial Behzadi
9f27654729 Update Persian translation 2020-04-24 20:13:04 +00:00
Dz Chen
f4013c7a5c Update Chinese (China) translation 2020-04-18 09:59:29 +00:00
Kristjan SCHMIDT
9e7eff4a3e Update Esperanto translation
(cherry picked from commit c5246b7415)
2020-04-18 09:00:54 +00:00
Florian Müllner
5b2bdd138a user-themes: Support session mode styles
Session mode stylesheets are installed in gnome-shell's theme
directory instead of a subdirectory of the global themes direc-
tory.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/118
2020-04-17 16:33:03 +00:00
Florian Müllner
90d3c5c51d workspace-indicator: Overhaul prefs widget
Inline toolbars are an outdated UI pattern, and both the toolbar widget
and the inline styling have been removed from GTK4. Making sure the
extension doesn't get in the way of a future GTK4 port is a good excuse
for modernizing the UI, so do just that :-)

Replace treeview and toolbar with an editable list as outline in the HIG:
https://developer.gnome.org/hig/stable/lists.html.en

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/120
2020-04-17 17:54:15 +02:00
Milan Crha
b00e531626 window-list: Invalid current mode selected in Preferences
It seems that gtk+ resets the active radio whenever a new radio button
is added into the group, thus rather restore the current mode after
the group is fully populated.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/119
2020-04-17 09:37:13 +02:00
Florian Müllner
b1c1b01184 po: Update POTFILES.in
The user-themes extension actually never had translatable strings.
2020-04-12 04:41:53 +02:00
Florian Müllner
739b1e11a0 user-themes: Add preference widget
While we don't endorse or support 3rd party theming, the extension
exists and is actively used. However right now the most convenient
way of setting it up is by installing Tweak Tool; give users an
alternative by providing a simple settings dialog ourselves.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/117
2020-04-12 04:13:25 +02:00
Florian Müllner
a3541ff0d9 ci: Drop "regular" build job
We already do a meson build/install when exporting extension bundles, and
now that the syntax check is handled by the CI instead of `meson test`,
the job just duplicates work.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/116
2020-04-11 01:08:11 +02:00
Florian Müllner
8fb5476a1c build: Drop syntax-checks from meson test
Those checks are just as well handled by the CI, and removing them
makes for a nice build system cleanup.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/116
2020-04-11 01:08:02 +02:00
Florian Müllner
fc8a46f15a ci: Syntax-check js sources
This is currently done as part of `ninja test`, but doing the check
in a separate CI job means it can run in parallel with other review
jobs and fail before trying to build.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/116
2020-04-11 01:07:55 +02:00
Florian Müllner
2e21f7cf72 ci: Combine commit/source checks under 'review'
The current names are an artifact from when flatpak-ci used
review/stop_review jobs. 'review' is a much better name and
matches what gnome-shell itself uses.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/116
2020-04-11 01:07:45 +02:00
Florian Müllner
a317d79016 ci: Set a default image
All jobs but one use the same issue, so specify that globally instead
of for each job.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/116
2020-04-11 01:07:37 +02:00
Florian Müllner
4722b89cc3 cleanup: Don't linebreak before closing parentheses
Otherwise recent versions of eslint want "dangling" commas,
which is at least ugly considering that most functions don't
allow adding arguments at leisure.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/116
2020-04-11 01:03:38 +02:00
Florian Müllner
5a4b71ba90 ci: Create and expose extension bundles
Similar to how we let CI create flatpaks for application, create
and expose extension bundles for easier testing.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/114
2020-04-10 23:57:09 +02:00
Florian Müllner
a6ee142f21 build: Omit unneeded translations from zip files
Each extension zip we create includes the translations of all extensions,
which is clearly wasteful. Avoid that by generating per-extension .pot
files and filtering out unnecessary translations.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/114
2020-04-10 23:11:43 +02:00
Florian Müllner
35427ed4f1 build: Use gnome-extensions-tool for zipping up
The tool has a dedicated command for creating an extension bundle. It
knows how to handle translations and GSettings schemas, so we don't
have to.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/114
2020-04-10 23:11:43 +02:00
Florian Müllner
bce63d3168 places-menu: Emphasize eject buttons here as well
We already align the buttons correctly here, but otherwise they can
use the same treatment as in the drive-menu.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/223
2020-04-10 14:31:40 +00:00
Florian Müllner
0426d1d8d5 drive-menu: Emphasize eject buttons as distinct controls
The buttons currently appear more as an attachment to the label
than as distinct controls. Address that by:

 - applying .button styling
 - increasing spacing between label and button
 - aligning buttons at the end

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/issues/223
2020-04-10 14:31:40 +00:00
Xiaoguang Wang
f9aaa732b2 windowPicker: Wrong signal ID _nWorkspacesNotifyId
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/106
2020-04-10 16:27:41 +02:00
Florian Müllner
7b82c5e12b ci: Update URL check
Gitlab started inserting a /-/ in its URLs, account for that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/-/merge_requests/113
2020-04-10 16:19:27 +02:00
Yosef Or Boczko
db305687d5 Update Hebrew translation
(cherry picked from commit c477f10bfb)
2020-04-01 15:22:54 +00:00
Florian Müllner
f527fe3774 build: Post-release version bump
... and official start of the next development cycle.
2020-03-31 01:03:14 +02:00
Florian Müllner
3428bebb67 Update sass submodule 2020-03-31 00:57:31 +02:00
Daniel Korostil
73822dc5f5 Update Ukrainian translation 2020-03-10 20:46:17 +00:00
Florian Müllner
961757f717 Bump version to 3.36.0
Update NEWS.
2020-03-07 23:07:37 +01:00
Florian Müllner
7d5c985004 build: Switch to js68 for tests
It's what the cool kids use nowadays ...
2020-03-07 23:07:37 +01:00
Florian Müllner
cd16995503 Update sass submodule 2020-03-07 23:00:47 +01:00
Florian Müllner
3a3b5bac85 Bump version to 3.35.92 2020-03-01 02:22:25 +01:00
Florian Müllner
9f6b83eece Update sass submodule 2020-03-01 02:22:02 +01:00
Florian Müllner
4456b440d8 Bump version to 3.35.91
Update NEWS.
2020-02-18 00:36:15 +01:00
Florian Müllner
f61e2f5f5c Update sass submodule 2020-02-18 00:35:32 +01:00
Zander Brown
a8eecac0ff Update British English translation 2020-02-11 19:32:35 +00:00
Florian Müllner
9a6b4da33c Bump version to 3.35.90
Update NEWS.
2020-02-06 21:54:51 +01:00
Florian Müllner
cb53d0b85c Update sass submodule 2020-02-06 21:51:09 +01:00
Umarzuki Bin Mochlis Moktar
318b9b18af Update Malay translation 2020-01-27 12:27:08 +00:00
Florian Müllner
cdf970d4b6 ci: Fix eslint job
eslint requires a file/directory, and will fail when the parameter
is not specified. Unfortunately it only indicates the failure by
printing its help output, but not via its return value, so our test
still completes successfully.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/105
2020-01-26 23:43:18 +01:00
Florian Müllner
1ee3803265 window-list: Fix typo
Whoops, missed a shift-press there. Another issues that sneaked
in thanks to the broken eslint check.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/105
2020-01-26 23:43:18 +01:00
Florian Müllner
b25c4d07a7 style: Avoid unnecessary parentheses
The eslint check in CI is broken, and some style nits weren't caught
as a consequence.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/105
2020-01-26 23:43:18 +01:00
Florian Müllner
330e7b312d windowsNavigator: Adjust to deprecated API removal
The old raise/lower methods have been deprecated for years, and
mutter finally removed those APIs.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/104
2020-01-26 23:30:55 +01:00
Florian Müllner
01f921541f windowsNavigator: Use normal inheritance for non-GObject class
More fallout from commit 63615cb657.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/104
2020-01-26 23:30:55 +01:00
Florian Müllner
cc52f4a260 windowsNavigator: Add missing imports
Commit 63615cb657 missed that, which is an easy mistake to make.

But how on earth did CI not catch this?!

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/104
2020-01-26 23:25:38 +01:00
sicklylife
eb71474c95 Update Japanese translation 2020-01-20 22:21:08 +00:00
sicklylife
69681cdc9a Update Japanese translation 2020-01-20 22:13:20 +00:00
Florian Müllner
c958e2d0fd window-list: Force single-line window titles
While window titles really really shouldn't contain newline characters,
they are under application control and therefore may very well do.
Force the corresponding labels to be single line, to prevent offending
applications from messing up the whole window list layout.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/202
2020-01-17 15:03:54 +01:00
Florian Müllner
9c964eaf1b drive-menu: Stop using deprecated child properties
StBoxLayout's child properties were deprecated in favor of the generic
expand/align properties.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/102
2020-01-09 20:16:39 +01:00
Florian Müllner
0500480d75 window-list: Stop using deprecated child properties
StBoxLayout's child properties were deprecated in favor of the generic
expand/align properties.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/102
2020-01-09 20:15:52 +01:00
Florian Müllner
37a09b7be1 apps-menu: Stop using deprecated (child) properties
StBoxLayout's child properties were deprecated in favor of the generic
expand/align properties.

StBin now uses the same Clutter.Actor properties instead of its own.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/102
2020-01-09 20:13:11 +01:00
Florian Müllner
d8c734124d classic: Add new import
The shell SCSS got reorganized, and we are now missing an import in
the classic style. Add it to get back a working classic style.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/101
2020-01-09 19:33:34 +01:00
Florian Müllner
25b6b562d9 windowPicker: Adjust to gnome-shell changes
WorkspacesDisplay now takes an adjustment for the workspace position,
provide that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/100
2020-01-09 19:25:25 +01:00
Florian Müllner
f2315d28f9 Update sass submodule 2020-01-09 18:29:44 +01:00
Florian Müllner
9b93931de6 Bump version to 3.35.3
Update NEWS.
2020-01-05 13:23:09 +01:00
Florian Müllner
47a2fd36e1 Update sass submodule 2020-01-05 13:23:09 +01:00
Fran Dieguez
be19802f78 Update Galician translation 2019-12-25 14:29:08 +00:00
Florian Müllner
35746251fd Bump version to 3.35.2
Update NEWS.
2019-12-11 18:59:03 +01:00
Willy Stadnick
a2b014ccbf screenshot-window-sizer: Fix cycling through all valid sizes
When cycling through window sizes, we should skip any sizes that are
bigger than the available area. We do that, but the current code
assumes that the possible sizes are sorted, which is no longer the
case since the addition of "phone" sizes in commit 5b43d4733c.

As a result, we may now skip sizes that would fit perfectly fine.
Address this by filtering out invalid sizes beforehand instead of
assuming a certain order (wich no longer work due to the addition
of a portrait format).

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/97
2019-11-26 00:49:08 +01:00
Florian Müllner
95131dc252 workspace-indicator: Exclude DESKTOP windows from window previews
While nautilus removed its desktop support a while ago in favor of an
extension, it's still possible that some external X11 desktop icon app
is used. As DESKTOP windows cannot be moved between workspaces or stacked,
and aren't perceived as regular windows, it doesn't make sense to show
them as previews in the workspace switcher.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/93
2019-11-21 21:42:16 +00:00
Florian Müllner
f3acb27d61 window-list: Exclude DESKTOP windows from window previews
While nautilus removed its desktop support a while ago in favor of an
extension, it's still possible that some external X11 desktop icon app
is used. As DESKTOP windows cannot be moved between workspaces or stacked,
and aren't perceived as regular windows, it doesn't make sense to show
them as previews in the workspace switcher.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/93
2019-11-21 21:42:16 +00:00
Florian Müllner
a904d51cf7 window-list: Fix faking overview
The public overview properties are now read-only, so switch to the
private properties which back them to fake the overview visibility.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/96
2019-11-21 22:38:50 +01:00
Florian Müllner
30ad3d670f extensions: Stop setting GTypeName
The type name generated by gjs now includes the filename, so we
don't have to set it ourselves to make sure it's unique.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/95
2019-11-21 22:25:43 +01:00
Marco Trevisan (Treviño)
63615cb657 cleanup: Use inheritance for Actor classes instead of composition
Use GObject types when inheriting from native actor classes.

Related to https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/89
2019-11-21 21:22:26 +00:00
Florian Müllner
a894897770 Bump version to 3.34.1
Update NEWS.
2019-10-09 03:04:32 +02:00
Florian Müllner
1b2c0a4b6c Update sass submodule 2019-10-09 03:04:32 +02:00
Yi-Jyun Pan
8e8b0392a2 Update Chinese (Taiwan) translation 2019-10-08 11:31:58 +00:00
Ask Hjorth Larsen
aea57f0305 Updated Danish translation 2019-10-02 05:54:09 +02:00
Dušan Kazik
6462af30ee Update Slovak translation 2019-09-26 07:15:50 +00:00
Nathan Follens
8d658f7e0d Update Dutch translation 2019-09-25 10:55:33 +00:00
Xiaoguang Wang
05bcd981cd data: Adjust to g-s-d's plugin removals
Remove "org.gnome.SettingsDaemon.Clipboard" and
"org.gnome.SettingsDaemon.Mouse", now the function is moved to
gnome-shell/mutter.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/94
2019-09-17 09:09:22 +08:00
Florian Müllner
ecf608ead8 Revert "ci: Import run-eslint script from gnome-shell"
Filtering errors by changed lines in a merge request means some
errors can slip through, for example when an import becomes unused
but isn't removed.

That's more common than rules changing behind our back, so revert
to running eslint directly again.

This reverts commit 119da3291b.
2019-09-14 01:55:58 +02:00
Florian Müllner
4ad50ab035 Bump version to 3.34.0
Update NEWS.
2019-09-09 20:32:39 +02:00
Sabri Ünal
934d17db4b Update Turkish translation 2019-09-06 20:09:49 +00:00
Milo Casagrande
b25e9541ce Update Italian translation 2019-09-06 08:41:27 +00:00
Efstathios Iosifidis
3204fd7842 Update Greek translation 2019-09-05 16:28:15 +00:00
Rafael Fontenelle
808f75e998 Update Brazilian Portuguese translation 2019-09-05 05:22:30 +00:00
Florian Müllner
56ecc684cc Bump version to 3.33.92
Update NEWS.
2019-09-04 23:30:47 +02:00
Goran Vidović
67ceca8f70 Update Croatian translation 2019-09-03 15:50:36 +00:00
Fabio Tomat
953445d6cf Update Friulian translation 2019-08-28 07:35:27 +00:00
Ryuta Fujii
cb834f9fa1 Update Japanese translation 2019-08-27 13:00:02 +00:00
Ryuta Fujii
ca2cd844b2 Update Japanese translation 2019-08-27 12:58:15 +00:00
Changwoo Ryu
98b3da41e8 Update Korean translation 2019-08-26 11:17:23 +00:00
Fran Dieguez
c00c749c0b Update Galician translation 2019-08-25 16:13:27 +00:00
Claude Paroz
e11c90365b Updated French translation 2019-08-25 10:44:16 +02:00
Balázs Úr
c812fdc134 Update Hungarian translation 2019-08-24 19:56:32 +00:00
Matej Urbančič
9299db49fb Updated Slovenian translation 2019-08-24 20:05:57 +02:00
Rūdolfs Mazurs
3a15dffe76 Update Latvian translation 2019-08-24 14:33:04 +00:00
Tim Sabsch
3df4e5fdbb Update German translation 2019-08-23 19:29:11 +00:00
Марко Костић
c0a5d0d091 Update Serbian translation 2019-08-21 21:16:23 +00:00
Florian Müllner
d36a196540 Bump version to 3.33.91
Update NEWS.
2019-08-21 20:00:22 +00:00
Florian Müllner
9077687c0a places-menu: Fix loop
Fix fallout from commit 63c07bdc73.
2019-08-21 20:00:22 +00:00
Florian Müllner
fcbfaec53e apps-menu: Adjust to mutter API change
The global grab API got dropped from mutter's Clutter fork, so use the
corresponding input device API instead.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/90
2019-08-21 19:39:11 +02:00
Florian Müllner
7c170e7e90 cleanup: Always use type-safe comparisons
The type coercion performed by the regular == and != operators can
have surprising results. It is therefore considered good practice
to use the type-safe === and !== variants instead.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:44 +00:00
Florian Müllner
ed7a292805 cleanup: Don't use comparison operator when checking falsy values
We mostly use the regular == and != comparison operators over their
type-safe === and !== counterparts. This is about to change, but there
are some places where we don't care whether a value is null, undefined
or 0; just check for falsiness there instead of using operators, so
we can start to consistently use the type-safe operators everywhere
else in a follow-up commit.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:44 +00:00
Florian Müllner
eb79f5b512 cleanup: Require "dangling" commas
Since ES5, trailing commas in arrays and object literals are valid.
We generally haven't used them so far, but they are actually a good
idea, as they make additions and removals in diffs much cleaner.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:44 +00:00
Florian Müllner
eceff51ba1 cleanup: Use consistent brace style of blocks
Our coding style has always been to avoid braces when all blocks
are single-lines. Make sure we apply that style consistently.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:44 +00:00
Florian Müllner
63c07bdc73 cleanup: Don't shadow variables
Having variables that share the same name in overlapping scopes is
confusing and error-prone, and is best avoided.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:44 +00:00
Florian Müllner
fdc3dda484 cleanup: Fix stray/missing spaces
Those are wrong according to our style guidelines, but the previous
eslint ruleset didn't catch them.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:44 +00:00
Florian Müllner
fca516e58a cleanup: Disambiguate assignments in arrow functions
As arrow functions have an implicit return value, an assignment of
this.foo = bar could have been intended as a this.foo === bar
comparison. To catch those errors, we will disallow these kinds
of assignments unless they are marked explicitly by an extra pair
of parentheses.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
c14f7f6fb8 cleanup: Use consistent style for ternary operator
We are currently inconsistent whether to put the operators in front
of the corresonding line or at the end of the preceding one. The
former makes more sense, so go with that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
2497dc6d31 cleanup: Use object destructuring where possible
ES6's destructuring is a nice way of assigning a variable in a concise way,
without duplicating the name of the object property. Use it consistently
where possible.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
a1f38d818d cleanup: Use some more array destructuring
Array destructuring has been supported by gjs/mozjs for quite some time,
so we are already using it heavily where it makes sense.

However one place still sneaked through where using destructuring makes
sense, as the element's position has semantic meaning (instead of just
making it the first, second, ... element).

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
9646149f9a cleanup: Use object shorthand where possible
ES6 allows to omit property names where they match the name of the
assigned variable, which makes code less redundant and thus cleaner.
We will soon enforce that in our eslint rules, so make sure we use
the shorthand wherever possible.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
b6d02f8e1f cleanup: Use operator shorthands where possible
Shorthands like a += b are well-established, so prefer them over the
less concise a = a + b.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
5f96b3c11c cleanup: Don't omit parens when constructing
While it is legal to omit parentheses when invoking a constructor
with no arguments, we generally avoid that in our coding style.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
e217f23767 cleanup: Avoid unnecessary parentheses
Extra parentheses usually add noise rather than clarity, so avoid
them.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
579a290bae screenshot-window-sizer: Rearrange calculation
eslint has a rule to prohibit unnecessary parentheses. While this is
generally a good idea stylistically, the parentheses in a calculation
of (a / b) * c add more clarity, as a / b * c lacks the unambiguity of
proper math notation:

   a                a
  --- * c   vs   -------
   b              b * c

We can still follow the style rule by rearranging to the unambiguous
c * a / b.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
2dc4325a90 places-menu: Use spread operator for variadic function
Invoking functions via Function.prototype.apply() and .call() is
less performant than a regular function call, and makes code harder
to read.

Before ES6 there was no other way of writing a function with variadic
arguments, but since we now have the spread operator, we can use that
as the better alternative.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
376502e952 windowsNavigator: Don't add linebreak before operator
When breaking overly long conditions into multiple lines, the operator
should end the previous line instead of starting the new one.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
91c9982d7f workspace-indicator: Remove some inactive code
This code has been commented out since it was added, presumably due to
difficulty in avoiding a cycle of reloading rows on settings changes
and writing settings on row changes.

Considering that the setting changing while the preference dialog is
up is extremely unlikely, don't bother with making it work and just
remove the dead code.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
c721121a2d native-window-placement: Fix weird comment styles
Don't use gtk-doc style comments for regular comments, and WTF is
/// comment ////?!

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
4007b61cf2 apps-menu: Minor cleanup
We have a much more idiomatic way of transforming one array
into another than pushing values while iterating over the
original array ...

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Florian Müllner
2655419880 lint: Sync configuration with gjs
gjs updated its eslint configuration to a much more complete and
thorough set.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/91
2019-08-21 15:13:43 +00:00
Danial Behzadi
9f1b52c852 Update Persian translation 2019-08-21 11:31:51 +00:00
Jordi Mas
d375cac32e Update Catalan translation 2019-08-21 09:18:10 +02:00
Piotr Drąg
66e2b32c8f Update Polish translation 2019-08-20 19:24:05 +02:00
Daniel Mustieles
95dd651b29 Updated Spanish translation 2019-08-20 12:43:32 +02:00
Aurimas Černius
1534e50a15 Updated Lithuanian translation 2019-08-18 22:07:01 +03:00
Florentina Mușat
23781abead Update Romanian translation 2019-08-18 12:25:30 +00:00
Jiri Grönroos
8065d38fdd Update Finnish translation 2019-08-17 13:00:55 +00:00
Kukuh Syafaat
05faa0763b Update Indonesian translation 2019-08-16 08:44:06 +00:00
Marek Černocký
e88cd44b3c Updated Czech translation 2019-08-16 10:20:25 +02:00
Florian Müllner
85fa282153 lint: Convert eslint JSON to YAML
gjs will change its configuration to YAML, so switch to that format
to keep syncing possible.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/90
2019-08-14 16:34:45 +00:00
Florian Müllner
119da3291b ci: Import run-eslint script from gnome-shell
Since we dropped the legacy configuration, we run eslint directly
instead of via a script. However gnome-shell's variant of the script
also has special treatment of merge requests to only consider errors
in changed lines.

While we strive for zero errors, new errors can appear when we update
eslint or change the configuration. Not blocking merge requests due
to unrelated eslint errors is a good thing, run eslint through a
modified version of the gnome-shell script.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/90
2019-08-14 16:34:45 +00:00
Anders Jonsson
6675d1c55d Update Swedish translation 2019-08-12 19:32:37 +00:00
Asier Sarasua Garmendia
be1a22069a Update Basque translation 2019-08-12 06:20:02 +00:00
Asier Sarasua Garmendia
2b9162b79d Update Basque translation 2019-08-11 13:48:18 +00:00
Florian Müllner
6aab09bd06 screenshot-window-sizer: Fix imports
Since we replaced Tweener with Clutter animations, we must import the
latter and don't need the former.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/88
2019-08-10 18:33:18 +02:00
Florian Müllner
c336e7d70e Bump version to 3.33.90
Update NEWS.
2019-08-10 00:41:55 +02:00
Florian Müllner
f486dfa112 Update sass submodule 2019-08-10 00:40:11 +02:00
Florian Müllner
80de26dc16 cleanup: Stop using Tweener
gnome-shell added convenience API for Clutter animations and replaced
Tweener everywhere; follow suite and do the same.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/87
2019-08-10 00:27:20 +02:00
Florian Müllner
af6f5fea54 window-list: Adjust animation time
gnome-shell changed all animations times to use milliseconds.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/86
2019-08-10 00:25:08 +02:00
Florian Müllner
9743054174 window-list: Don't override existing signal
Since commit b6a6de9bb5 turned WindowPicker into a ClutterActor
subclass, we already have a 'scroll-event' signal and don't need
to define our own.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/86
2019-08-10 00:25:08 +02:00
Florian Müllner
827af154b8 window-list: Support showing windows from all workspaces
gnome-panel's window list applet has such an option, so let's support
it as well.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/154
2019-08-09 22:20:43 +00:00
Jor Teron
f9b87f9b44 Update Karbi translation 2019-07-25 10:46:02 +00:00
Florian Müllner
a41bcd4f10 Bump version to 3.33.4
Update NEWS.
2019-07-20 18:09:56 +02:00
Piotr Drąg
1a13f29b0c Update POTFILES.in 2019-07-20 14:01:47 +02:00
Florian Müllner
b6a6de9bb5 window-list: Actorize
gnome-shell is in the process of moving from composition to subclassing.
Do the same here, and use custom actor classes instead of "actor" and
"_delegate" properties.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/84
2019-07-20 00:20:51 +02:00
Florian Müllner
5b7631898c cleanup: Use GObject.NotImplementedError
Since version 1.50.0, gjs defines GObject.NotImplementedError for throwing
errors when a virtual method that requires a subclass implementation is not
defined.

So use this instead of a generic JS Error in such cases.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/84
2019-07-20 00:20:51 +02:00
Florian Müllner
f8bae05036 cleanup: Stop using PopupMenuItem.actor properties
Popup menu items are now actor subclasses, and their actor property
points to the item itself.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/84
2019-07-20 00:20:51 +02:00
Florian Müllner
60c75e5fcf classic: Add 'horizontal-workspaces' extension
Vertical workspaces are another defining characteristics of GNOME 3,
and thus rather un-classic. That switch was driven by the overall
layout of the overview, and now that we disable the overview in
GNOME Classic, we can just return to the traditional workspace
layout as well.

Add a small extension that does just that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/72
2019-07-19 13:54:09 +02:00
Florian Müllner
c6d2063f4d workspace-indicator: Show previews in workspace switcher
Currently the new horizontal workspace switcher only shows a series of
buttons, with no indication of the workspaces' contents. Go full GNOME 2
and add tiny draggable preview rectangles that represent the windows
on a particular workspace.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/77
2019-07-19 13:48:21 +02:00
Florian Müllner
52f373fb70 workspace-indicator: Support horizontal workspace layout
Just like we did for the workspace indicator in the window-list, improve
the handling of horizontal workspace layouts by showing the switcher
in-place instead of delegating the functionality to a menu.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:42:44 +02:00
Florian Müllner
283a1ec5c2 workspace-indicator: Minor cleanup
Pass the style class at construction time instead of setting it later.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:24:50 +02:00
Florian Müllner
c516f05927 workspace-indicator: Refactor workspace signal handlers
We are about to support a separate representation if horizontal
workspaces are used. To prepare for that, rename the handlers to
something more generic and split out menu-specific bits into a
dedicated helper function.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:24:50 +02:00
Florian Müllner
e836a9e5e0 workspace-indicator: Minor cleanup
Mutter has a dedicated method for getting the index of the active
workspace, use that instead of getting first the active workspace
and then its index.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:24:50 +02:00
Florian Müllner
d1674c5f75 workspace-indicator: Update workspace names in-place
There's no good reason to rebuild the entire menu on workspace names
changes, we can simply update the labels in-place.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:24:50 +02:00
Florian Müllner
9fa283877c workspace-indicator: Make some properties private
There's no reason why they should be public.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:24:50 +02:00
Florian Müllner
f1a154207f workspace-indicator: Fix whitespace error
We only want a single space before and after operators, not at least
one. Unfortunately eslint only enforces the latter ...

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/71
2019-07-19 13:24:50 +02:00
Florian Müllner
5b07dfded9 window-list: Show previews in workspace switcher
Currently the new horizontal workspace switcher only shows a series of
buttons, with no indication of the workspaces' contents. Go full GNOME 2
and add tiny draggable preview rectangles that represent the windows
on a particular workspace.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74
2019-07-19 13:16:40 +02:00
Florian Müllner
9f9dbd579b window-list: Turn workspace thumbs into drop targets
It makes some sense to allow using the workspace indicator for moving
windows between workspaces as well as for workspace switching. This
applies particularly in GNOME classic after we disabled the overview
there, so that there is again a non-shortcut way of moving windows
between workspaces.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/74
2019-07-19 13:15:52 +02:00
Florian Müllner
c9477dd94d window-list: Support horizontal workspace layout
Unlike in GNOME 2, the workspace indicator we display in the window list
isn't a workspace switcher, but a menu button that allows switching
workspaces via its menu. The reason for that is that a horizontal
in-place switcher would be at odds with the vertical workspace layout
used in GNOME 3.

However that reasoning doesn't apply when the layout is changed to a
horizontal one, so replace the button with a traditional workspace
switcher in that case.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:22 +02:00
Florian Müllner
5a30ebe403 window-list: Refactor workspace signal handlers
We are about to support a separate representation if horizontal
workspaces are used. To prepare for that, rename the handlers to
something more generic and split out menu-specific bits into a
dedicated helper function.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:15 +02:00
Florian Müllner
a5f347ba10 window-list: Improve workspace label styling
The border currently looks off - it extends all the way vertically
and leaves zero spacing to the label horizontally. Fix both issues
by setting appropriate padding/margins.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:09 +02:00
Florian Müllner
dab326c17e window-list: Minor cleanup
Mutter has a dedicated method for getting the index of the active
workspace, use that instead of getting first the active workspace
and then its index.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:09 +02:00
Florian Müllner
bdf6af3ee3 window-list: Update workspace names in-place
There's no good reason to rebuild the entire menu on workspace names
changes, we can simply update the labels in-place.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:09 +02:00
Florian Müllner
1532c15325 window-list: Make some properties private
There's no reason why they should be public.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:09 +02:00
Florian Müllner
cbd1b7d983 window-list: Use a more specific GTypeName for workspace indicator
Now that the class inherits from GObject, the generic name easily
conflicts with other classes otherwise, for example with the one
from the workspace-indicator extension.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:09 +02:00
Florian Müllner
4b9c53ff2e window-list: Split out workspaceIndicator
The extension has grown unwieldily big, so before starting to improve
on the workspace indicator, move it to its own source file.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/70
2019-07-19 13:11:09 +02:00
Florian Müllner
6eb3a62e2b apps-menu: Add drop-shadow to application icons
... to make sure they are readable on light backgrounds.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/168
2019-07-18 11:17:04 +00:00
Florian Müllner
0469fc6aa9 Update sass submodule (again) 2019-07-18 12:32:15 +02:00
Florian Müllner
1f6f22010e Update sass submodule 2019-07-18 12:24:15 +02:00
Jakub Steiner
ae1b17d29c classic: Update window-list styling
Make buttons flatter, rounder to match default styling.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/82
2019-07-16 11:17:11 +02:00
Jakub Steiner
3fa750ce17 classic: No special casing of notifications
The default already handles light variant.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/82
2019-07-16 11:17:10 +02:00
Jakub Steiner
56e2a570e3 classic: hover state for panel buttons
- prelight before active
- lighten up slightly, similar to what the default does (inverted)

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/169
2019-07-15 23:45:03 +02:00
Jor Teron
167f0be6b4 Update Karbi translation 2019-07-16 02:51:57 +00:00
Jor Teron
80eb29bd51 Add Karbi translation 2019-07-14 04:30:50 +00:00
Florian Müllner
f2b261c573 window-list: Handle closing window picker with Escape
Just like the overview can be closed with Escape, it makes sense to
allow the same for the window picker (in addition to pressing super
repeatedly).

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/80
2019-07-02 21:20:01 +02:00
Florian Müllner
6c49ca825c window-list: Move super-key handling into WindowPicker
We have an option to put a window list on each monitor, so we may have
more than one window picker toggle. We don't want each of those try to
toggle the window picker simultanuously, so move handling of the super
key directly into the picker.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/80
2019-07-02 21:20:01 +02:00
Florian Müllner
6a25971366 lint: Also allow camelcase for default signal handlers
on_some_signal() is used less than vfunc_some_method(), but it can
still be useful.
2019-07-02 02:44:22 +02:00
Florian Müllner
dc3523a344 lint: Remove misleading globals
While those are defined by gnome-shell, we generally want to define our
own with the correct gettext domain.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/79
2019-06-29 03:07:56 +02:00
Florian Müllner
2ef6dba0a5 window-list: Fix resetting handler ID
This is embarrassing, although destroy() is expected to only run once,
so the bug shouldn't have an effect in practice.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/78
2019-06-29 02:56:33 +02:00
Florian Müllner
92db87f7cb window-list: Add window picker button
With the latest changes, GNOME Classic has become so classic that it
is bordering dull. Salvage at least a tiny piece of GNOME 3 in form
of a window-pick button which toggles an exposé-like reduced overview.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/73
2019-06-28 23:02:58 +02:00
Florian Müllner
82d2011061 classic: Disable overview
The overview is one of the defining features of GNOME 3, and thus
almost by definition at odds with the classic session, which
emulates a traditional GNOME 2 desktop.

Even with the less prominent placement inside the application menu
it never quite fit in - it doesn't help that besides the different
UI paradigma, the overview keeps its "normal" styling which differs
greatly with classic's normal mode.

So besides removing the "Activities" button via the session mode
definition, now that the apps-menu extension doesn't replace it anymore,
disable the overview completely in the classic session.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
2019-06-28 20:55:28 +00:00
Florian Müllner
545b811562 apps-menu: Hide overview when launching app
Now that we no longer hide the overview when the menu is opened,
it is possible to activate menu entries from the overview. Start
hiding the overview in that case, which is consistent with app
launching elsewhere.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
2019-06-28 20:55:28 +00:00
Florian Müllner
d99d0a06bd apps-menu: Stop hiding the overview when toggled
Now that the extension no longer doubles as the "Activities" button,
that behavior is confusing.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
2019-06-28 20:55:28 +00:00
Florian Müllner
6105eecff2 apps-menu: Stop taking over Activities button
We don't want the "Activities" button in GNOME Classic, but the current
way of handling it is confusing:

 - the button is hidden, but the corresponding hot corner
   sometimes works (when the application menu isn't open)

 - the button is effectively moved inside the menu, although
   it's clearly not an app or category

 - the apps-menu can be used independent from classic mode, in
   which case removing the "Activities" button may not be wanted

Address those points by removing any handling of the activities button
from the apps-menu extension. We will remove it again from the classic
session via a session mode tweak.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
2019-06-28 20:55:28 +00:00
Florian Müllner
d1254d9b57 places-menu: Don't hardcode position
The extension currently assumes that we have the "Activities" button
at the left of the top bar. This is currently true, not only in the
regular session, but also in GNOME classic where the button is hidden
(but still present).

However this is about to change: We will stop taking over the button
from the apps-menu extension, and instead disable "Activities" from
the session mode definition.

Prepare for this by adding the places menu before the application menu
instead of assuming a hardcoded position.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/69
2019-06-28 20:55:28 +00:00
Florian Müllner
2db4589dea cleanup: Re-order imports
They should be grouped between external (GI/gjs) and shell and in
alphabetical order. Until commit bab4be1a ExtensionUtils was special
as it was required for some imports, but that's no longer the case
for most extensions.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/76
2019-06-28 21:51:38 +02:00
Florian Müllner
dfeb99fc0a apps-menu: Add missing chain-up
PanelMenu.Button is a bit weird in that it also "contains" its parent
actor. That container is supposed to be destroyed with the button, but
as we currently don't chain up to the parent class' _onDestroy(), we
leave behind an empty container every time the extension is disabled.

Fix this by adding the missing chain-up.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/75
2019-06-27 04:26:35 +02:00
Florian Müllner
48ea80d391 Bump version to 3.33.3
Update NEWS.
2019-06-24 20:34:02 +02:00
Jakub Steiner
b138e218bb classic: fix a broken build
- redesign of the default theme nuked some local variables
  breaking the build.
2019-06-24 20:28:03 +02:00
Florian Müllner
829440f546 Update sass submodule 2019-06-24 20:02:18 +02:00
Marco Trevisan (Treviño)
14859b4009 window-list: Pass the actor as PopupMenuManager owner
PopupMenuManager's grabHelper starting from gnome-shell@7bb84da must be
an actor, so pass it explicitly instead of expecting the shell to do it
for us.

This fixes an error during pushModal that was causing a grab not to be
released.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/68
2019-05-29 14:45:43 -05:00
Florian Müllner
3a596054ad places-menu: Adjust to GObject-ification of menu items
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/67
2019-05-29 09:38:21 +00:00
Florian Müllner
65191d83b4 drive-menu: Adjust to GObject-ification of menu items
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/67
2019-05-29 09:38:21 +00:00
Florian Müllner
8499b0e254 apps-menu: Adjust to GObject-ification of menu items
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/67
2019-05-29 09:38:21 +00:00
Florian Müllner
f166ca501f window-list: Stop using deprecated actor property
Since PanelMenu.Button was changed to inherit from St.Widget, its actor
property is deprecated and points to itself. Stop using it to avoid the
corresponding warning.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/67
2019-05-29 09:38:21 +00:00
Florian Müllner
a36331522f Bump version to 3.33.2
Update NEWS.
2019-05-22 18:58:31 +00:00
Florian Müllner
25e43a5d08 lint: Remove legacy configuration
After the last batch of indentation changes, the whole code base
conforms to the new style now, so we can drop the legacy eslint
configuration.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:19 +02:00
Florian Müllner
ad914441a2 window-list: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:19 +02:00
Florian Müllner
200d337769 apps-menu: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:19 +02:00
Florian Müllner
e56f1a976e native-window-placement: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:19 +02:00
Florian Müllner
6a66cd4fa6 places-menu: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:19 +02:00
Florian Müllner
55c493389a auto-move-windows: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:18 +02:00
Florian Müllner
06f1303834 drive-menu: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:18 +02:00
Florian Müllner
3d5687ae3c workspace-indicator: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:18 +02:00
Florian Müllner
cdd3fba593 screenshot-window-sizer: Reindent to conform with new style
Instead of aligning arguments like we used to do, use a consistent
four-space indent as mandated by gjs' current style guide.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/66
2019-05-22 20:40:18 +02:00
Florian Müllner
f11c101878 Bump version to 3.33.1
Update NEWS.
2019-05-14 17:53:56 +00:00
Florian Müllner
7c412ca7d9 window-list: Don't use anchor point
It is deprecated and we can easily replace it with a translation.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/64
2019-04-28 11:08:02 +00:00
Florian Müllner
e3a6e8f82c Bump version to 3.32.1
Update NEWS.
2019-04-17 22:09:40 +02:00
Florian Müllner
ce10ad64c4 Update sass submodule 2019-04-17 22:06:50 +02:00
Adrien Plazas
5b43d4733c screenshot-window-sizer: Add phone screenshot sizes
This is going to be convenient to take fake screenshots for phones like
the Librem 5.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/65
2019-04-12 14:31:53 +02:00
Florian Müllner
3671d5a299 cleanup: Use an extension object instead of globals
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/143
2019-04-08 06:00:29 +00:00
Florian Müllner
a024d9f005 windowsNavigator: Use subclasses instead of injections
gnome-shell moved to ES6 classes, which means the constructor is
no longer a regular method that we can swap out with an injected
version.

Instead, do our modifications in subclasses and use them to replace
the original classes.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/143
2019-04-08 06:00:29 +00:00
Fabian P. Schmidt
d94a3500f6 README: Re-add extension alternate-tab with obsolescence notice
This commit adds a short notice about the former extension
alternate-tab to the README. This notice should be removed once
the traffic of users searching for this obsolete extension settled
down.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/62
2019-03-20 12:00:08 +01:00
Florian Müllner
78141e6433 Bump version to 3.32.0
Update NEWS.
2019-03-12 00:02:14 +01:00
Florian Müllner
dd53fb8eb7 Update sass submodule 2019-03-12 00:01:26 +01:00
Mart Raudsepp
6cd2be452b Update Estonian translation 2019-03-10 17:27:41 +00:00
Kristjan SCHMIDT
36abd576b5 Update Esperanto translation 2019-03-06 21:15:21 +00:00
Victor Ibragimov
730547b3e1 Update Tajik Translation 2019-03-06 21:03:41 +05:00
Florian Müllner
e7e6b882a3 Bump version to 3.31.92
Update NEWS.
2019-03-05 06:07:01 +01:00
Florian Müllner
53f92f2910 Update sass submodule 2019-03-05 06:05:05 +01:00
Florian Müllner
a26380d56e user-theme: Clarify some code
Commit 2582ab accidentally pointed out that the current theme loading code
obfuscates which directories are searched for themes. Rewrite it with modern
JS features to make it more obvious.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:18 +01:00
Florian Müllner
ab334d95e0 Revert "User theme: compatibility with XDG Base Directory"
We already handled themes in XDG_DATA_HOME before commit 2582ab
by prepending it to the system dirs.

This reverts commit 2582ab4fd0.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
7e5726e632 apps-menu: Promisify marking file as trusted
Use async/await to make nested operations easier to read.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
95b40069bf apps-menu: Remove unnecessary check
The function is always called with an array parameter (albeit it may
be empty), so remove the unnecessary check and cut down on indentation.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
bd9f1cfd91 apps-menu: Avoid deep nesting
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
81548ced69 native-window-placement: Clarify some code
Add some intermediate variables for better legibility.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
a378e5fc34 placesDisplay: Promisify launching
Use async/await to make nested async operations easier to read.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
56d19ad480 placesMenu: Add early return to reduce indentation level
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
a071685c13 auto-move-windows: Clarify some code
Apply some tricks to align column numbers with their corresponding
values for better legibility.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
599428d292 auto-move-windows: De-duplicate row appending
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
1f1f9664a6 cleanup: Share unmount/eject arugments
Besides the callback, eject and unmount share the same arguments.
Make this explicit by sharing the common arguments between branches.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
fb039c0fb5 cleanup: Use Meta.MaximizeFlags.BOTH
This shorthand has been around for a long time, use it make (un)maximize
code more readable.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/60
2019-03-04 19:35:10 +01:00
Florian Müllner
6e63edd737 lint: Sync with gjs
Some of our custom rules have been upstreamed[0], update the
rule sets accordingly.

[0] https://gitlab.gnome.org/GNOME/gjs/merge_requests/272
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/59
2019-03-03 05:54:58 +01:00
Florian Müllner
55ecd3939e ci: Switch to extension-ci image
gnome-shell now provides a docker image with useful tools for extension CI;
as it contains everything we need, we can speed up CI by not running the
package manager.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/58
2019-02-28 23:54:46 +01:00
Florian Müllner
d83d6e857a style: Use single-quotes for translated strings
The coding style of using double quotes for translatable strings
and single quotes otherwise is unnecessarily complex and cannot
be enforced with an eslint rule.

Simply use single quotes consistently for all strings.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:29:31 +01:00
Florian Müllner
db35d7ae7c style: Change indentation style of object literals
Instead of keeping the first property on the same line as the opening
brace and aligning the properties, use a four-space indent. This brings
us closer to gjs' coding style, and as a bonus helps keeping lines in
the soft 80 character limit.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:29:24 +01:00
Florian Müllner
d34b5030b9 style: Use a consistent style for array literals
Most array literals already use a four-space indent, except the ones in
GObject metainfo and function parameters. Reindent those as well to make
the style consistent and bring it closer to gjs' coding style.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:29:14 +01:00
Florian Müllner
7f8f1234ae style: Stop using braces for single-line arrow functions
Braces are optional for single-line arrow functions, but there's a
subtle difference:
Without braces, the expression is implicitly used as return value; with
braces, the function returns nothing unless there's an explicit return.

We currently reflect that in our style by only omitting braces when the
function is expected to have a return value, but that's not very obvious,
not an important differentiation to make, and not easy to express in an
automatic rule.

So just omit braces consistently as mandated by gjs' coding style.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:29:05 +01:00
Florian Müllner
9b25a227c6 style: Don't exempt ternary expressions from indent rule
It turns out we can comply with gjs' coding style and still align the
branches if line breaks are required, so do that to reduce diversion
from the canonical GNOME style.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:28:55 +01:00
Florian Müllner
78580bc3a8 lint: Remove unused rules
We picked those up from Polari, which had those for

 - object arrays:
    let foo = [
        { bar: 42,
          quz: true },
        { bar: 23,
          quz: false }
    ];

 - "enums":

    let Options = {
        ONE:   0,
        TWO:   1,
        THREE: 2
    };

We don't have either of those, so drop the rules to minimise divergence
with gjs.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:28:44 +01:00
Florian Müllner
b50074fd37 lint: Restrict deprecated Lang API
Now that we moved to ES standard replacements, let's make sure they
don't creep back in accidentally.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/57
2019-02-28 23:28:33 +01:00
Florian Müllner
d5a1044244 Bump version to 3.31.91
Update NEWS.
2019-02-21 22:41:20 +01:00
Florian Müllner
11cad1f3b3 Update sass submodule
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/56
2019-02-21 22:23:52 +01:00
Tomasz Gąsior
2582ab4fd0 User theme: compatibility with XDG Base Directory
See https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/55
2019-02-20 01:15:49 +01:00
Gun Chleoc
5a06de606d Update Scottish Gaelic translation
(cherry picked from commit c394dbefba216e685fb01c4268c7bb0db93728ff)
2019-02-16 09:34:54 +00:00
Florian Müllner
4671c24b78 places-menu: Stop using deprecated Mainloop module
Just use the underlying GLib functions directly.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/54
2019-02-16 00:49:44 +01:00
Florian Müllner
0d41643866 cleanup: Use destructuring for imports from GI
This is *much* nicer than repetitive "imports.gi" lines ...

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/54
2019-02-16 00:49:44 +01:00
Florian Müllner
d8f7d70c10 apps-menu: Remove outdated legacy-tray handling
The tray is long gone, so trying to access it will result in
warnings.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/53
2019-02-16 00:40:55 +01:00
Florian Müllner
cbd981351e ci: Check for issue/MR URLs in commit messages
Commit messages should include the full URL to an issue or merge
request to keep associated information easily available in future
log digging.

Jonas came up with a script to enforce that policy for mutter and
gnome-shell. It's an excellent idea, so adopt it here as well.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/52
2019-02-16 00:03:49 +01:00
Matej Urbančič
434185ba03 Added Slovenian translation 2019-02-12 20:52:31 +01:00
Florian Müllner
abc8877d11 Update sass submodule 2019-02-07 17:44:44 +01:00
Florian Müllner
a7ff9f401e Bump version to 3.31.90
Update NEWS.
2019-02-06 22:34:06 +01:00
Florian Müllner
bab4be1a59 extensions: Drop Convenience library
Its methods are now provided by gnome-shell itself and can be used
as an easy drop-in replacement.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/44
2019-02-06 20:17:59 +01:00
Florian Müllner
47beeb1a8e ci: Allow gradual switch to new style
It doesn't make too much sense to declare parts of the existing style
"legacy", but then enforce it via CI. To allow for a gradual switch,
generate a report with all issues that eslint considers errors in both
configurations.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:36 +01:00
Florian Müllner
945eddbc26 ci: Add "source_check" stage
More testing is always good, and the static analysis that eslint
provides goes well beyond what js60 offers, so run it as part of
the CI.

This will also ensure that new contributions comply with the style
rules we have set up.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:30 +01:00
Florian Müllner
c37ba0878a ci: Don't use global image/before_script
We are about to add another job that will use different parameters,
so it makes sense to set them under the job they belong to rather
than globally.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:25 +01:00
Florian Müllner
3861ffae31 extensions: Mark exported symbols
eslint obviously doesn't know about gnome-shell's extension API, so
the various entry points trigger unused-variable errors. To fix,
explicitly mark those symbols as exported.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:20 +01:00
Florian Müllner
2081309679 lib: Mark globals used from other modules as exported
eslint cannot figure out that those symbols are used from other modules
via imports, so they trigger unused-variable errors. To fix, explicitly
mark those symbols as exported.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:15 +01:00
Florian Müllner
08a04b2f02 cleanup: Mark unused (but useful) variables as ignored
While we aren't using those destructured variables, they are still useful
to document the meaning of those elements. We don't want eslint to keep
warning about them though, so mark them accordingly.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:09 +01:00
Florian Müllner
7b363fd659 cleanup: Mark unused arguments as unused
This will stop eslint from warning about them, while keeping their
self-documenting benefit.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:51:02 +01:00
Florian Müllner
85112394b3 lint: Allow marking variables/arguments as unused
Unused variables or arguments can indicate bugs, but they can also
help document the code, in particular in case of signal handlers
and destructuring.

Account for this by keeping the error, but set up patterns that allow
us to opt out of if for individual variables/arguments. For arguments
we pick a '_' prefix, while for variables we go with a suffix instead,
to not accidentally exempt private module-scope variables.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:53 +01:00
Florian Müllner
190243ee89 lint: Add "legacy" configuration
Regarding coding style, gjs is moving in a direction that departs quite
significantly from the established style, in particular when indenting
multi-line array/object literals or method arguments:

Currently we are keeping those elements aligned, while the gjs rules now
expect them to use the regular 4-space indentation.

There are certainly good arguments that can be made for that move - it's
much less prone to leading to overly-long lines, and matches popluar JS
styles elsewhere. But switching coding style implies large diffs which
interfere with git-blame and friends, so in order to allow for a more
gradual change, add a separate set of "legacy" rules that match more
closely the style we would expect up to now.

It also disables the rules for quotes and template strings - the former
because we cannot match the current style to use double-quotes for
translatable strings and single-quotes otherwise, the latter because
template strings are still relatively new, so we haven't adopted them
yet.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:45 +01:00
Florian Müllner
1141d996d9 lint: Don't require indent for GObject.registerClass()
That function will eventually be replaced with decorators, and we don't
want to re-indent all GObject classes when that happens, so allow class
declarations with no indent:

    GObject.registerClass(
    class Foo extends GObject.Object {
    });

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:38 +01:00
Florian Müllner
f7cbd0d600 lint: Tweak indenting rule
I simply cannot deal with multi-line trinary expressions where the
two "branches" don't align, so add an exception for them.

And while the strict 4-line indent for objects is growing on me for
"regular" objects:

    let foo = new Foo({
        bar: 42,
        baz: 'bam'
    });

I do prefer the current style of compact braces and aligned properties
for object lists:

    let entries = [
        { name: 'foo',
          visible: true },
        { name: 'bar',
          halign: Gtk.Align.START }
    ];

So allow the latter style as well, at least for the time being.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:31 +01:00
Florian Müllner
c704f0de55 lint: Allow single-line braces
When using arrow functions, we only omit the braces when we are using
the return value:

    this.get_children().filter(w => w.visible);

When braces are used, eslint by default enforces line breaks, but
there are cases where the expression is hardly less concise than
the above:

    this.get_children().forEach(w => { w.destroy(); });

So change the default to allow this.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:19 +01:00
Florian Müllner
c8a1cd9c99 lint: Allow multiple spaces before key values
This is useful for imitating namespaced flags/enums:

```
const FooFlags = {
    NONE :   0,
    SMEAGLY: 1 << 0,
    SMOGLEY: 1 << 1,
    MUGGLY:  1 << 2
};
```

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:10 +01:00
Florian Müllner
ff79588d3b lint: Enforce camelCase
All variables should be in camelCase, so configure the corresponding
rule to enforce this. Exempt properties for now, to accommodate the
existing practice of using C-style underscore names for construct
properties of introspected objects.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:50:05 +01:00
Florian Müllner
8ae84703a4 lint: Enforce arrow notation
We replaced all Lang.bind() calls with arrow functions or the standardized
Function.prototype.bind(), at least for the former eslint has some options
to ensure that the old custom doesn't sneak back in.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:49:59 +01:00
Florian Müllner
f18b281020 lint: Require spaces inside braces in object literals
Prohibiting spaces where the established GNOME style has required
them for a decade would be a harsh change for no good reason.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:49:54 +01:00
Florian Müllner
75503b5f3c lint: Tweak the whitelist of globals
gjs doesn't include any gettext wrappers, and obviously can't know
about the shell's global object, so include those in the list of
globals.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:49:42 +01:00
Florian Müllner
1d96f83362 lint: Import eslint rules from gjs
gjs started to run eslint during its CI a while ago, so there is an
existing rules set we can use as a starting point for our own setup.

As we will adapt those rules to our code base, we don't want those
changes to make it harder to synchronize the copy with future gjs
changes, so include the rules from a separate file rather than using
the configuration directly.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/50
2019-01-28 06:49:31 +01:00
Florian Müllner
b3f009017c style: Use consistent style for object literal parameters
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
05d961dfe1 style: Avoid trailing commas in array destructuring
When destructuring multiple return values, we often use trailing commas
to indicate that there are additional elements that we are ignoring.

There isn't anything inherently wrong with that, but it's a style that's
too confusing for eslint - on the one hand we require a space after a
comma, on the other hand we require no space before closing brackets.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
8a2b9abc09 style: Stop using string concatenation
String concatenation is considered bad style after ES6 added
template strings. The latter is the replacement we generally
want, except where the aforementioned xgettext bug would trip
over the backtick/slash combination.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
3effc9cfc2 style: Fix indentation errors
While we have some style inconsistencies - mostly regarding split lines,
i.e. aligning to the first arguments vs. a four-space indent - there are
a couple of places where the spacing is simply wrong. Fix those.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
1be7061da0 style: Fix stray/missing spaces
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
f75d1d75af style: Fix stray/missing semi-colons
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
67f9e4c419 style: Use space after catch
We currently use a consistent style of not adding spaces in catch
clauses, however that's inconsistent with the style we use for any
other statement. There's not really a good reason to stick with it,
so switch to the style gjs/eslint default to.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
aaeff6d12b style: Use camelCase for variable names
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
912ba1e651 cleanup: Remove unhelpful unused init() argument
Virtually all extensions use the getCurrentExtension() helper instead
of the obscure init() argument, and we are no exception.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
b741b1bbe2 cleanup: Remove empty init() functions
The method is optional, so there's no point at all in letting the
shell call an empty method during initialization.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
d7414025a5 cleanup: Remove unused variables
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
a317d75f70 cleanups: Clean up unused imports
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
194e294d2c user-theme: Don't use concatenation to build filenames
Since template strings were added in ES6, string concatenation is
considered bad style. There's a catch though: xgettext currently
has a nasty bug concerning the combination of backticks and slashes.
Avoid that issue by building filenames with the corresponding GLib
helper function.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
a092da2527 apps-menu: Remove unused function parameter
It hasn't been used since commit d86044f383.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/49
2019-01-28 06:37:28 +01:00
Florian Müllner
4655cde002 build: Bump js-shell used for syntax checks
gjs moved from SpiderMonkey 52 to 60 during the last cycle, it's time
we follow suit.
2019-01-28 06:35:26 +01:00
Florian Müllner
0a979f5bfa extensions: Remove alternate-tab left-over
This fell through the cracks in commit d731534d04.
2019-01-28 02:11:07 +01:00
Pieter Schalk Schoeman
d2046bb2c6 Update Afrikaans translation 2019-01-20 23:05:23 +00:00
Charles Monzat
a2f40952b3 Update French translation
(cherry picked from commit 4231e4794ff1e30060b8ecdb404c02a829da3241)
2019-01-17 17:12:23 +00:00
Ryuta Fujii
29917bcb1b Update Japanese translation 2019-01-03 05:10:57 +00:00
Florian Müllner
1b881e1eaa Bump version to 3.31.2
Update NEWS.
2018-11-14 02:21:07 +01:00
Florian Müllner
40a8ab60f4 Update sass submodule 2018-11-14 02:21:07 +01:00
Piotr Drąg
b684e756e2 Update POTFILES.in 2018-11-13 01:26:18 +01:00
Florian Müllner
7eae32eb76 workspace-indicator: Don't override ClutterActor.destroy()
Now that PanelMenu.Button was made an StWidget subclass, the destroy()
method actually maps to the ClutterActor method, and overriding it
results in warnings when the extension is disabled. So instead, use
the existing ::destroy handler.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
34c20e6176 workspace-indicator: Stop using compatibility actor property
PanelMenu.Button sets up a `this.actor = this` property for compatibility,
but let's reflect the actual new object hierarchy.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
62818e71e9 workspace-indicator: Adjust to gnome-shell changes
PanelMenu.Button is now a GObject subclass, so initialization must
happen in _init() rather than constructor().

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
ee85839d60 drive-menu: Don't override ClutterActor.destroy()
Now that PanelMenu.Button was made an StWidget subclass, the destroy()
method actually maps to the ClutterActor method, and overriding it
results in warnings when the extension is disabled. So instead, use
the existing ::destroy handler.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
d9932b8f55 drive-menu: Stop using compatibility actor property
PanelMenu.Button sets up a `this.actor = this` property for compatibility,
but let's reflect the actual new object hierarchy.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
efa882080f drive-menu: Adjust to gnome-shell changes
PanelMenu.Button is now a GObject subclass, so initialization must
happen in _init() rather than constructor().

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
132b3b0509 places-menu: Don't override ClutterActor.destroy()
Now that PanelMenu.Button was made an StWidget subclass, the destroy()
method actually maps to the ClutterActor method, and overriding it
results in warnings when the extension is disabled. So instead, use
the existing ::destroy handler.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
e5a0616a0a places-menu: Stop using compatibility actor property
PanelMenu.Button sets up a `this.actor = this` property for compatibility,
but let's reflect the actual new object hierarchy.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
fbeb3cf1e9 places-menu: Adjust to gnome-shell changes
PanelMenu.Button is now a GObject subclass, so initialization must
happen in _init() rather than constructor().

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
072fbee7cb apps-menu: Stop using compatibility actor property
PanelMenu.Button sets up a `this.actor = this` property for compatibility,
but let's reflect the actual new object hierarchy.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
e9928b3c08 apps-menu: Adjust to gnome-shell changes
PanelMenu.Button is now a GObject subclass, so initialization must
happen in _init() rather than constructor().

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
2af737a8c2 apps-menu: Remove pointless destroy() implementation
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
321702fd15 window-list: Stop using compatibility actor property
PanelMenu.Button sets up a `this.actor = this` property for compatibility,
but let's reflect the actual new object hierarchy.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
60493faf96 window-list: Don't override ClutterActor.destroy()
Now that PanelMenu.Button was made an StWidget subclass, the destroy()
method actually maps to the ClutterActor method, and overriding it
results in warnings when the extension is disabled. So instead, use
the existing ::destroy handler.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
821cbf9328 window-list: Adjust to gnome-shell changes
PanelMenu.Button is now a GObject subclass, so initialization must
happen in _init() rather than constructor().

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/113
2018-11-12 23:42:06 +00:00
Florian Müllner
cc0f167c0e extensions: Remove example extension
There are plenty of extension examples out there, no need to include
a sample extension that doesn't show-case any useful functionality
but puts additional burden on distributors to exclude it from packaged
extensions.
2018-11-13 00:19:45 +01:00
Florian Müllner
d731534d04 extensions: Remove alternate-tab
Ever since GNOME 3.8 when gnome-shell started to provide the window
switcher functionality itself, the extension has only existed to
change the default behavior of the alt-tab shortcut in the classic
session. Now that we achieve this behavior with a per-desktop override,
there's no longer a need for the extension, so remove it altogether.

Users who prefer the window switcher over the default app switcher
can use the regular keyboard settings to assign a shortcut to the
"Switch windows" action.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-11-13 00:14:44 +01:00
Florian Müllner
94eba47358 Bump version to 3.30.1
Update NEWS.
2018-10-08 22:55:05 +02:00
Florian Müllner
d34933de0b Update sass submodule 2018-10-08 22:50:52 +02:00
Florian Müllner
9410bdfad6 window-list: Ignore hidden buttons when scrolling
Window lists are per-monitor, so workspaces are implemented by
simply hiding all buttons that correspond to windows/apps on
other workspaces. That means we need to take the visibility
into account when handling scroll-events to switch through the
list, or else we'll end up switching "randomly" between workspaces.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/78
2018-10-06 16:05:46 +00:00
Florian Müllner
d424b0f645 window-list: Minor clean-up
Modern javascript has explicit methods for locating the first
element of an array that meets a certain condition, use those
instead of manually looping over the array.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/78
2018-10-06 16:05:46 +00:00
Florian Müllner
c0454db0c6 appsMenu: Consider scale-factor in height computation
Actor heights are in physical pixels, while CSS measures are in logical
pixels, so we need to adjust accordingly to prevent the scale factor
from being applied twice.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/102
2018-09-23 17:31:03 +02:00
Florian Müllner
913b2ba691 Bump version to 3.30.0 2018-09-04 00:10:36 +02:00
Florian Müllner
ba51869b93 Bump version to 3.29.91
Update NEWS.
2018-08-20 15:48:53 +02:00
Florian Müllner
ffe6110ea9 Stop using conditional catch statements
They are a mozilla extension that is going away in SpiderMonkey 60.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/90
2018-08-13 12:00:22 +02:00
Florian Müllner
8b1bcc9fed Bump version to 3.29.90
Update NEWS.
2018-08-01 03:47:30 +02:00
Florian Müllner
ebad80c64d Update sass submodule 2018-08-01 03:46:05 +02:00
Florian Müllner
39caf951e0 data: Use override for default alt-tab keybindings
Per-desktop overrides aren't limited to keys in org.gnome.mutter, so
we can use them instead of the alternate-tab extension to default to
the window switcher in the classic session.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-09 19:18:54 +02:00
Florian Müllner
ecf28e13b4 window-list: Use correct settings schemas
Override schemas are gone (yay!), so we can now simply use the original
schema independent from the used session mode.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-09 19:18:54 +02:00
Florian Müllner
a01b44f7de data: Replace override schema with per-desktop override
GSettings now recognizes per-desktop overrides that can be used
to change schemas' default values for classic mode, so use that
instead of the separate override schema we currently use with
mutter's custom override mechanism.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-09 19:18:54 +02:00
Florian Müllner
6b1926bab3 Bump version to 3.29.3
Update NEWS.
2018-07-09 19:09:13 +02:00
Florian Müllner
64986740e3 Update sass submodule 2018-07-09 19:08:15 +02:00
Jonas Ådahl
6583eae622 Remove usage of MetaScreen
As of the libmutter API version 3 MetaScreen does no longer exist.
Functionality that previously depended on MetaScreen has been moved
elsewhere (e.g. MetaDisplay or MetaWorkspaceManager etc).

https://bugzilla.gnome.org/show_bug.cgi?id=759538
2018-07-06 19:53:08 +02:00
Florian Müllner
9add688abf Actually bump version number
Gah ...
2018-05-24 19:06:33 +02:00
Florian Müllner
a85764a0ab Bump version to 3.29.2
Update NEWS.
2018-05-24 19:04:07 +02:00
Florian Müllner
eaa2c7857e Update submodule URL
gnome-shell-sass was migrated to gitlab, so update to the correct URL
instead of relying on the redirect.
2018-05-24 19:04:07 +02:00
Florian Müllner
6e1b5bc346 Update sass submodule 2018-05-24 19:01:36 +02:00
Florian Müllner
f59ab1272d drive-menu: Disconnect volume monitor signals
The handler IDs were renamed at some point, resulting in the signals
not being disconnected on disable.
2018-05-10 18:56:23 +02:00
Florian Müllner
f25ffe6f63 build: Include translations in uploaded zip files
The meson port accidentally dropped translations from the generated
zip files for uploading to extensions.gnome.org, add them back.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/69
2018-05-07 12:00:19 +02:00
Florian Müllner
6746061898 Bump version to 3.28.1
Update NEWS.
2018-04-13 20:30:56 +02:00
Florian Müllner
3dc9f2e4ff cleanup: Use Array.includes() to check for element existence
This is a relatively recent addition to the standard we can use where we
don't care about the actual position of an element inside the array.
(Array.includes() and Array.indexOf() do behave differently in edge cases,
for example in the handling of NaN, but those don't matter to us)
2018-04-12 11:05:41 +02:00
Florian Müllner
682d6a8fd1 window-list: Handle no overrides settings
We can only know about override settings that are provided by the
upstream GNOME or GNOME Classic sessions, but not any custom sessions
created by admins, users or distributions. Handle that case by falling
back to the original settings.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/62
2018-04-12 11:05:41 +02:00
Dz Chen
d3ea985e14 Update zh_CN translation 2018-03-21 19:21:17 +08:00
Xiaoguang Wang
496ae16cf1 apps-menu: Duplicate destroy actor
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/59
2018-03-13 09:06:00 +08:00
Florian Müllner
0554e0deb9 Bump version to 3.28.0
Update NEWS.
2018-03-12 21:57:46 +01:00
Bruce Cowan
c0c938977c Update British English translation 2018-03-10 18:05:48 +00:00
Aman Alam
8ee207d74d Update Punjabi translation 2018-03-10 15:37:59 +00:00
Xiaoguang Wang
0e625bedba data: Remove nautilus classic
nautilus doesn't support nautilus classic from version 3.27
2018-03-07 12:49:37 +08:00
Florian Müllner
127b5e6c25 ci: Install mozjs-devel instead of gjs-devel
All we are really interested in is mozjs' js52 utility for running
syntax checks - gjs has significantly more dependencies, so cut
down on time and bandwidth spent on downloading and installing
unneeded packages.

This cuts down the number of packages we install from 202 to 13,
and the download size from 133M to 17M.
2018-03-06 01:07:43 +01:00
Florian Müllner
64c17acc0a ci: Use latest stable Fedora
Rawhide is being very rawhide right now, so unbreak CI by using
the latest stable release.
2018-03-05 23:58:42 +01:00
Florian Müllner
0102b2800a Bump version to 3.27.92
Update NEWS.
2018-03-05 23:42:34 +01:00
Daniel Șerbănescu
7c66434616 Update Romanian translation 2018-03-03 13:06:18 +00:00
GNOME Translation Robot
f9ae518c9d Update Scottish Gaelic translation
(cherry picked from commit 0f2baf3e566a7b96f9c472db1fe2802a2354aeba)
2018-02-26 12:54:09 +00:00
Piotr Drąg
55ba3c086a Fix Spanish translation header 2018-02-24 00:20:16 +01:00
Florian Müllner
d22e603686 build: Fix classic .session definition
Session files should be installed with the .session extension, not
.desktop ...
2018-02-22 15:26:36 +01:00
Florian Müllner
3e0d8bd56f build: Fix xsession installation dir 2018-02-22 15:26:36 +01:00
Florian Müllner
45ac2cd403 Bump version to 3.27.91
Update NEWS.
2018-02-22 13:40:15 +01:00
Florian Müllner
a808380d04 Update sass submodule 2018-02-22 13:40:15 +01:00
Florian Müllner
5c0ef12d13 build: Require sassc for classic style
Meson has a strict separation of source- and build directory, and
expects anything generated in the latter. That means that in order
to maintain our current setup - shipping the generated CSS in the
repo while also optionally updating it automatically when sassc is
found - we have to fight the build system to some extent, which makes
it less reliable than we would like.

Since we switched to sassc which is a more acceptable build-time
dependency than the original ruby-based tool, just drop the CSS
from the repo and unconditionally generate it from SASS if classic
mode is enabled.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/merge_requests/28
2018-02-22 10:59:55 +00:00
Piotr Drąg
b80aa8ee11 Remove po/Makevars
Meson doesn’t use it, and Damned Lies learned to read po/meson.build.
2018-02-21 00:05:55 +01:00
Jeremy Bicha
7de345fc8b data: Adjust to another g-s-d plugin removal 2018-02-17 15:54:41 -05:00
Jonas Kümmerlin
ff3adb8429 classic: fix panel gradient in overview
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/40
2018-01-28 20:22:41 +01:00
Jonas Kümmerlin
3398e74005 classic: never show drop shadow for panel icons
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/39
2018-01-28 20:21:24 +01:00
Jonas Kümmerlin
f9ad051367 classic: make notifications legible again
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/41

As requested in discussion about !26, this is resolved by
switching to a light background.
2018-01-28 01:15:10 +01:00
Florian Müllner
ae65a82fdd classic: Fix "Clear All" button readability
Most buttons appear in modal dialogs which keep their normal
appearance in the classic theme, except for the calendar's
"Clear All" which needs a dark text color to be readable on
the light background.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/26
2018-01-18 13:53:09 +01:00
Florian Müllner
2dbe692a31 Revert last two commits
Gah, nasty accident :-(
2018-01-18 13:44:54 +01:00
Florian Müllner
7de28858e1 WIP: Disable places-menu extension
For whatever reason it prevents the classic session to come up?!
2018-01-18 13:26:15 +01:00
Florian Müllner
8881fbcc9d classic: Fix "Clear All" button readability 2018-01-18 13:26:15 +01:00
Florian Müllner
3b5a1486de auto-move-windows: Track apps' windows instead of window creation
We currently track window creation to decide whether the new window
should be moved or not. In order for this to work, the window must
already have been matched to the correct application, which is only
the case when the properties used for app matching were supplied
during window creation.

This is usually the case on X11, but never on wayland. To avoid this
issue altogether, stop listening for raw window creations, and instead
track when a window is added to an application we are interested in.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/33
2018-01-18 13:26:15 +01:00
Florian Müllner
0721ed6504 auto-move-windows: Cache app configuration in map
While reading the configuration, processing it and iterating over the
configured apps to find a match isn't terribly expensive, but caching
the configuration in a map does save a bit of work, and makes for much
cleaner code in findAndMove().

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/33
2018-01-18 13:26:15 +01:00
Florian Müllner
ec98cff9d9 auto-move-windows: Minor style cleanups
Use camelCase for variable names, call the first index variable 'i'
instead of 'j', and fix some whitespace errors.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/33
2018-01-18 13:26:15 +01:00
Florian Müllner
9ecd6bbb13 auto-move-windows: Remove unused imports
https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/33
2018-01-18 13:26:15 +01:00
Florian Müllner
3b6cd04a59 auto-move-windows: Do not copy checkWorkspaces() method
When overriding an upstream method, copying the original method code
should always be a last resort, as the two code bases tend to get
out of sync and it often becomes hard to spot the modifications done
by the override. Both those issues can be avoided when figuring out
a way to split out the modifications and call the unmodified upstream
method - we are in luck with our checkWorkspaces() override, as we
can trick the upstream method into not removing workspaces we want
to keep instead of copying the method altogether.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/33
2018-01-18 13:26:15 +01:00
Florian Müllner
3284fe81d7 places-menu: Don't force dispose() of uninitialized proxies
Trying to dispose a proxy object before it has been properly
initialized triggers an "uncatchable exception", which gjs
treats as a fatal error since commit c7bdcaab4. We only have
anything to clean up once the proxy is initialized anyway, so
don't force dispose() before that.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/44
2018-01-17 22:48:45 +01:00
Florian Müllner
39274f286c places-menu: Minor style tweak
Reindent function parameters to fit the old-fart 80-character limit
for better readability.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/44
2018-01-17 22:48:31 +01:00
Florian Müllner
eba3cfccfe build: Include UUID suffix in classic mode description
The shortnames we use elsewhere don't match the actual UUID, so we
effectively don't enable any extensions in classic mode at the moment.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/45
2018-01-17 19:04:48 +01:00
Florian Müllner
f5c69cbfdc build: Fix generated classic session definition
The list of enabled extensions should be an array of strings, so add
quotes instead of just dumping the extension names into the file.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/45
2018-01-17 19:04:37 +01:00
Florian Müllner
c668392462 build: Install schema overrides for classic mode
This was lost accidentally when porting to meson.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/45
2018-01-17 19:04:22 +01:00
Florian Müllner
22e416c09b window-list: Fix icons not showing for some windows on wayland
On wayland, the properties that are used for application matching
are generally set after the window has been created, so it is
normal that buttons start with the fallback icon. While we already
track the properties that are relevant for app matching, our signal
handler may run before the window is matched to its app.

Make sure the WindowTracker gets to process those signals first by
using connect_after() for our own handlers.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/10.
2017-12-25 10:29:20 +01:00
Iñigo Martínez
9dc183af23 build: Fix description of the enable_extensions option
The description of the `enable_extensions` was wrong since it
changed to the `array` type, because the extension separator
is now a comma instead of space.
2017-12-20 17:41:24 +01:00
Iñigo Martínez
6a0a247668 build: Use the new array type
meson 0.44 features a new option type called `array` that allows
more than one string to be passed.

This feature fits perfectly the `enable_extensions` option needs,
so it has been changed to be an `array` type. the option has not
been limited to a set of choices to avoid duplication.
2017-12-20 10:41:30 +01:00
Florian Müllner
2aaf4370b6 meta: Update description note for reporting bugs
We no longer take bugs in bugzilla.
2017-12-01 21:04:02 +01:00
Florian Müllner
ba27cc4a64 cleanup: Get rid of Lang.bind()
After replacing Lang.Class with ES6 classes and adopting arrow notation
for anonymous callbacks, we only use the Lang module to bind `this` to
named callbacks. However since ES5, this functionality is already provided
by Function.prototype.bind() - in fact, Lang.bind() itself uses it when
no extra arguments are specified.

So just use the built-in function directly instead of the wrapper.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:50:52 +01:00
Florian Müllner
acb44de469 cleanup: Port GObject classes to ES6 classes
GJS added API for defining GObject classes with ES6 class syntax
last cycle, use it to port the remaining Lang.Class classes to
the new syntax.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:50:52 +01:00
Florian Müllner
48399d46c0 cleanup: Port non-GObject classes to ES6 classes
ES6 finally adds standard class syntax to the language, so we can
replace our custom Lang.Class framework with the new syntax. Any
classes that inherit from GObject will need special treatment,
so limit the port to regular javascript classes for now.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:50:46 +01:00
Florian Müllner
30e7ff5a8f cleanup: Use method syntax
Modern javascript has a short-hand for function properties, embrace
it for better readability and to prepare for porting to ES6 classes.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:50:28 +01:00
Florian Müllner
968ae427f1 cleanup: Use arrow-notation for anonymous functions
Arrow notation is great, but as we only started using it recently,
we currently have a wild mix of Lang.bind(), function() and () => {}.
To make the style consistent again, change all anonymous functions
to arrow notation.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:40:32 +01:00
Florian Müllner
4ee30a5445 cleanup: Replace tabs with spaces
Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:38:38 +01:00
Florian Müllner
d3bbeb1b0c cleanup: Fix some coding style issues
Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/30
2017-12-01 20:38:38 +01:00
Florian Müllner
9d5b149428 ci: Add initial gitlab continuous integration
Continuous integration is good, in particular when used before
merging a change to master as allowed by gitlab. And now that
we enabled some basic syntax checking of source files, we even
have something useful to test for ...

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/32
2017-12-01 20:30:48 +01:00
Florian Müllner
b90c99b87c build: Optionally syntax-check sources
As a pure javascript project, building is really just a glorified
copy operation, so success doesn't even indicate that sources are
syntactically correct (a.k.a. "compile-tested"). We can at least
get some minimal testing by performing some basic syntax checking
when SpilderMonkey's JS shell is available.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/32
2017-12-01 18:58:17 +01:00
Florian Müllner
ba38019049 build: Remove autotools support
Complete the switch to meson and drop autotools support ...

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/31
2017-12-01 17:43:21 +01:00
Florian Müllner
406f4cd170 docs: Update instructions for extension additions for meson
The steps for adding a new extension are clearly different in meson,
so update the instructions accordingly. Don't bother with keeping
the existing autotools steps - supporting both build systems in
parallel is just temporary, autotools is on its way out.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/31
2017-12-01 17:43:21 +01:00
Florian Müllner
a2c63a46d3 build: Add utility script to export zip files
We currently do have some Makefile magic to export zip files suitable
for uploading to extensions.gnome.org. As this is not easily replicated
in meson, add a small non-magic script for the same purpose.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/31
2017-12-01 17:41:07 +01:00
Florian Müllner
3ab01aebec build: Support the meson build system
Meson is on track to replace autotools as the build system of choice,
so support it in addition to autotools.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/31
2017-12-01 17:41:04 +01:00
Florian Müllner
c6ecf2c0df build: Update repo URL in metadata 2017-11-29 20:19:37 +01:00
Piotr Drąg
a26f9e34c7 places-menu: Use Unicode quotation marks in a new string
See https://developer.gnome.org/hig/stable/typography.html

https://bugzilla.gnome.org/show_bug.cgi?id=772211
2017-11-25 16:21:35 +01:00
Florian Müllner
21315d74c3 apps-menu: Support separators
We currently only load entries and directories, and ignore any
separators defined by the user/admin. Make some people happy
by supporting them ...

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/27
2017-11-25 06:46:29 +01:00
Florian Müllner
d86044f383 apps-menu: Minor code cleanup
The parameter to _clearApplicationBox() has never been used, so
remove it. In fact, modern javascript makes the function so compact
that we can just move the code inline.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/27
2017-11-25 06:46:29 +01:00
Florian Müllner
077a292952 apps-menu: Reload on tree changes
Now that we respect the sort order defined in the .menu file, make
sure to reload the menu on those changes as well, not just when
the installed apps themselves change.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/27
2017-11-25 06:46:29 +01:00
Florian Müllner
8bd35eeb09 apps-menu: Don't override sort order
Keep the order in which GMenu returns loaded apps, so users can
reorder entries in Alacarte.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/27
2017-11-25 06:46:29 +01:00
Rémy Lefevre
eb425ac8a2 places-menu: Support unmounting ejectable places
Being able to unmount places that can be ejected directly from the
menu is convenient and consistent with Nautilus, so add an eject
button to items that are removable.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/17
2017-11-25 06:22:16 +01:00
Florian Müllner
724249dd29 docs: Use markdown
Markdown produces nicer output where supported, so use that instead
of custom ASCII formatting.
2017-11-25 04:01:19 +01:00
Florian Müllner
76526a9c2d Update README
Over the years the list of extensions has become seriously outdated - a
number of extensions has long been removed, while others have been added.
With the switch to gitlab, the README is displayed prominently, so make
sure the list is accurate again.
2017-11-25 02:55:01 +01:00
Florian Müllner
29ea5ca1a9 build: Update bug tracker to gitlab 2017-11-25 02:52:40 +01:00
Kjartan Maraas
40c6b8b1d8 Updated Norwegian bokmål translation. 2017-11-06 13:41:21 +01:00
Florian Müllner
2460ac9df8 auto-move: Remove unused imports 2017-10-26 20:03:12 +02:00
Florian Müllner
8c551ba8ee windowsNavigator: Use regular for() loops
"for each ... in" has been deprecated for a long time and won't be
supported in upcoming SpiderMonkey versions, so replace it with
"for ... of" instead.
2017-10-26 20:03:12 +02:00
Matej Urbančič
99295c438d Updated Slovenian translation 2017-10-20 16:57:37 +02:00
Florian Müllner
f840f70052 Bump version to 3.27.1
Update NEWS.
2017-10-17 17:51:35 +02:00
Florian Müllner
ef99394ffb nativeWindowPlacement: Use custom strategy to hook into layout
Instead of copying a long function for a single changed line, wrap the
layout algorithm in a LayoutStrategy so the workspace code picks it
up without modifications.

https://bugzilla.gnome.org/show_bug.cgi?id=787934
2017-10-13 16:08:07 +02:00
Florian Müllner
778eebc421 nativeWindowPlacement: Handle captions-on-top settings changes
Currently the injection to move title captions to the top depends on
the value of the setting at the time the extension is enabled.
Instead, do the injections unconditionally and query the setting
inside the function to pick up settings changes.

https://bugzilla.gnome.org/show_bug.cgi?id=787934
2017-10-13 16:08:07 +02:00
Florian Müllner
97d1cbca19 naturalWindowPlacement: Don't copy relayout() function
To move title captions to the top, we can simply apply a translation
before calling the unmodified original function.

https://bugzilla.gnome.org/show_bug.cgi?id=787934
2017-10-13 16:08:07 +02:00
Florian Müllner
a0cae3d130 naturalWindowPlacement: Remove unused stuff
https://bugzilla.gnome.org/show_bug.cgi?id=787934
2017-10-13 16:08:07 +02:00
Florian Müllner
01893ca048 apps-menu: Fix whitespace errors 2017-10-13 16:08:07 +02:00
Xavi Ivars
c86a67823c [l10n] Updated Catalan (Valencian) translation 2017-10-05 14:01:50 +02:00
Florian Müllner
726be0692e Bump version to 3.26.1
Update NEWS.
2017-10-04 17:42:16 +02:00
Florian Müllner
f339001e22 data: Update style 2017-10-04 01:08:54 +02:00
Florian Müllner
530b165ddf nativeWindowPlacement: Adjust to overview changes
title._spacing is no longer defined, so we end up with bogus positions
when window-captions-on-top is set to true. Adjust the positioning to
do without that for now, though the whole extension could use a rewrite
to not copy everything-and-the-kitching-sink, or be killed off as yet
another extension from the original random collection that turned out
too expensive to keep dragging along ...

https://bugzilla.gnome.org/show_bug.cgi?id=787604
2017-10-04 01:06:42 +02:00
Anders Jonsson
e479068d84 Update Swedish translation 2017-10-02 18:50:24 +00:00
Piotr Drąg
824e79d83e gschema: Fix gettext-domain 2017-10-01 19:10:42 +02:00
Efstathios Iosifidis
0d18c3f70d Update Greek translation 2017-09-25 13:48:39 +00:00
Arash Mousavi
a682b66bbf Update Persian translation 2017-09-22 18:40:54 +00:00
Stas Solovey
f4510b9b04 Update Russian translation 2017-09-20 08:40:39 +00:00
Alexander Rüedlinger
c1143fa716 apps-menu: Use "0o" prefix for octal literals
In short, gjs complains that octal escape sequences are deprecated
and advises to use the "0o" prefix for octal literals. Do that to
fix the warning.

https://bugzilla.gnome.org/show_bug.cgi?id=787294
2017-09-17 23:18:52 +02:00
Alexander Rüedlinger
37b95a8498 apps-menu: Remove excess argument
This was an oversight in commit 63653406a3 when porting from a
removed Popover API to ClutterActor.add_child().

https://bugzilla.gnome.org/show_bug.cgi?id=787294
2017-09-17 23:18:52 +02:00
Alexander Rüedlinger
cccef0e857 places-menu: Fix JS warning
Define class PlacesManager with 'var' instead of 'const', to shut
up a gjs warning when accessing it from the extension.

https://bugzilla.gnome.org/show_bug.cgi?id=787291
2017-09-17 23:18:52 +02:00
Florian Müllner
592b4ebacf Bump version to 3.26.0
Update NEWS.
2017-09-12 19:26:30 +02:00
Ask Hjorth Larsen
3a799d519b Updated Danish translation 2017-09-10 18:10:56 +02:00
Lyubomir Vasilev
8b09c17684 Updated Bulgarian translation 2017-09-10 18:03:23 +03:00
Inaki Larranaga Murgoitio
f00ffcaa3d Update Basque language 2017-09-09 17:19:41 +02:00
Sveinn í Felli
82cc175df1 Update Icelandic translation 2017-09-08 06:08:48 +00:00
Sveinn í Felli
eda9eeef18 Update Icelandic translation
(cherry picked from commit c5467e8a804abce0c45b43502e4ac16649a99a53)
2017-09-08 06:05:02 +00:00
Lyubomir Vasilev
fb1d4faece Updated Bulgarian translation 2017-09-08 08:48:25 +03:00
Trần Ngọc Quân
3b1d7428df Updated Vietnamese translation
Signed-off-by: Trần Ngọc Quân <vnwildman@gmail.com>
2017-09-04 14:36:52 +07:00
Rafael Fontenelle
dca18f3614 Update Brazilian Portuguese translation 2017-09-03 13:29:46 +00:00
Changwoo Ryu
6a9b3a9369 Update Korean translation 2017-09-02 03:55:18 +00:00
Yuras Shumovich
373c3660a1 Update Belarusian translation 2017-09-01 14:56:50 +00:00
hanniedu
74fdac5dfd Updated Dutch translation Master 3.26 2017-09-01 10:37:25 +02:00
Jordi Mas
49c00f3282 Fixes to Catalan translations 2017-08-30 19:23:31 +02:00
Jiri Grönroos
b9a32a8f64 Update Finnish translation 2017-08-29 09:36:28 +00:00
Rūdolfs Mazurs
bf2074cd82 Update Latvian translation 2017-08-28 10:27:11 +03:00
Cheng-Chia Tseng
a659c3e586 Update Chinese (Taiwan) translation 2017-08-27 05:38:40 +00:00
Cheng-Chia Tseng
959dfee54e Update Chinese (Taiwan) translation 2017-08-27 03:45:29 +00:00
Milo Casagrande
714162fdd3 Update Italian translation 2017-08-26 15:40:48 +00:00
ST Alfas
856bda4270 Update Malayalam translation 2017-08-26 13:54:45 +00:00
Florian Müllner
5530229dd2 data: Update style 2017-08-22 13:08:23 +02:00
Florian Müllner
cdc3894400 Bump version to 3.25.91
Update NEWS.
2017-08-22 00:59:27 +02:00
Jordi Mas
f8f66f628e Update Catalan translation 2017-08-21 15:18:39 +02:00
Alexandre Franke
f8b9afda07 Update French translation 2017-08-19 16:41:37 +00:00
Мирослав Николић
617904e69f Updated Serbian translation 2017-08-14 21:27:38 +02:00
Furkan Tokaç
6e4be83dec Update Turkish translation 2017-08-13 11:38:56 +00:00
Rafael Fontenelle
66f0972a43 Update Brazilian Portuguese translation
(cherry picked from commit c15d9af98dde60e1ca3e215b6b36665ca9e4eef6)
2017-08-12 22:58:51 +00:00
Gianvito Cavasoli
e6bdbb2c68 Update Italian translation
(cherry picked from commit 825f1f2090690a7c93244e44e66fdc3213adc8f1)
2017-08-12 15:16:12 +00:00
Piotr Drąg
7d3915c30d Update Polish translation 2017-08-11 03:36:02 +02:00
Florian Müllner
a04ad6acd7 Bump version to 3.25.90
Update NEWS.
2017-08-10 20:41:34 +02:00
Florian Müllner
8778c16f2a data: Update style 2017-08-10 20:27:35 +02:00
Anders Jonsson
2917deead1 Update Swedish translation 2017-08-08 22:04:26 +00:00
Fran Dieguez
08fc96c7ee Update Galician translation 2017-08-07 13:04:57 +00:00
Balázs Meskó
35c01d7223 Update Hungarian translation 2017-08-04 13:29:12 +00:00
Piotr Drąg
71ba8b04d7 drive-menu: Add a translator comment explaining a variable
https://bugzilla.gnome.org/show_bug.cgi?id=687590
2017-08-03 14:06:26 +02:00
Anders Jonsson
c74077239e Update Swedish translation
(cherry picked from commit fa9243dae9d038233f23a48d2e88b8c49375dcdd)
2017-07-31 22:32:03 +00:00
Baurzhan Muftakhidinov
2c2d6b69ca Update Kazakh translation 2017-07-27 12:11:15 +00:00
Daniel Mustieles
dcf08375c1 Updated Spanish translation 2017-07-25 20:14:53 +02:00
gogo
15085df41f Update Croatian translation 2017-07-25 18:10:23 +00:00
Matej Urbančič
29780d495d Updated Slovenian translation 2017-07-21 16:07:26 +02:00
Alexander Rüedlinger
69700dc29b apps-menu: Remove more dead code
Commit 0a91893b02 removed dead code, namely a ::panel-box-changed signal
handler. Unfortunately, it forgot to remove the associated code that
disconnects the signal.

Signed-off-by: Alexander Rüedlinger <a.rueedlinger@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=785202
2017-07-21 10:09:13 +02:00
Alexander Rüedlinger
0a91893b02 apps-menu: Remove dead code
This fell through the cracks in commit 2d1d81247 when adjusting to
the gnome-shell changes that also removed the ::panel-box-changed
signal ...

Signed-off-by: Alexander Rüedlinger <a.rueedlinger@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=785200
2017-07-21 01:34:38 +02:00
170 changed files with 15189 additions and 15518 deletions

3
.eslintrc.yml Normal file
View File

@@ -0,0 +1,3 @@
extends:
- ./lint/eslintrc-gjs.yml
- ./lint/eslintrc-shell.yml

177
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,177 @@
include:
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/fedora.yml'
- remote: "https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/6f86b8bcb0cd5168c32779c4fea9a893c4a0c046/templates/ci-fairy.yml"
image: registry.gitlab.gnome.org/gnome/gnome-shell/fedora/34:2021-08-12.0
stages:
- pre_review
- prepare
- review
- build
- deploy
default:
# 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
LINT_LOG: "eslint-report.xml"
JS_LOG: "js-report.txt"
workflow:
rules:
- 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'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_COMMIT_BRANCH =~ /^gnome-[0-9-]+$/'
- when: 'manual'
.gnome-shell-extensions.fedora:34:
variables:
FDO_DISTRIBUTION_VERSION: 34
FDO_DISTRIBUTION_TAG: '2021-08-31.0'
FDO_DISTRIBUTION_PACKAGES: >
meson git gettext sassc
.prereview_req: &prereview_req
needs:
- check_commit_log
- check-merge-request
check_commit_log:
extends:
- .fdo.ci-fairy
stage: pre_review
script:
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
then
ci-fairy check-commits --junit-xml=commit-message-junit-report.xml ;
else
echo "Not a merge request" ;
fi
<<: *pipeline_guard
artifacts:
expire_in: 1 week
paths:
- commit-message-junit-report.xml
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
build-fedora-container:
extends:
- .fdo.container-build@fedora@x86_64
- .gnome-shell-extensions.fedora:34
stage: prepare
<<: *prereview_req
js_check:
stage: review
<<: *prereview_req
script:
- find extensions -name '*.js' -exec js78 -c '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG)
artifacts:
paths:
- ${JS_LOG}
when: on_failure
eslint:
stage: review
<<: *prereview_req
script:
- eslint -o $LINT_LOG -f junit --resolve-plugins-relative-to $(npm root -g) extensions
artifacts:
paths:
- ${LINT_LOG}
reports:
junit: ${LINT_LOG}
build-bundles:
stage: build
<<: *prereview_req
script:
- ./export-zips.sh
artifacts:
name: 'Extension bundles'
expose_as: 'Get Extension bundles here'
paths:
- zip-files/
fedora-build:
extends:
- .fdo.distribution-image@fedora
- .gnome-shell-extensions.fedora:34
stage: build
needs:
- build-fedora-container
before_script:
- git submodule update --init
script:
- meson setup build --werror -Dextension_set=all -Dclassic_mode=true
- meson compile -C build
- meson test -C build
- meson install -C build
artifacts:
paths:
- build
fedora-dist:
extends:
- .fdo.distribution-image@fedora
- .gnome-shell-extensions.fedora:34
stage: deploy
needs:
- fedora-build
before_script:
- git submodule update --init
script:
- meson dist -C build
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
- "**/meson.build"
- meson/*
fedora-dist-tarball:
extends: fedora-dist
artifacts:
expose_as: 'Get tarball here'
paths:
- build/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz
rules:
- if: '$CI_COMMIT_TAG'

View File

@@ -0,0 +1,13 @@
patterns:
deny:
- regex: '^$CI_MERGE_REQUEST_PROJECT_URL/(-/)?merge_requests/$CI_MERGE_REQUEST_IID$'
message: Commit message must not contain a link to its own merge request
- regex: '^extensions/'
message: Commit message subject should not be prefixed with 'extensions/', use the extension name instead
where: subject
- regex: '^[^:]+: [a-z]'
message: "Commit message subject should be properly Capitalized. E.g. 'window: Marginalize extradicity'"
where: subject
- regex: '^\S*\.js:'
message: Commit message subject prefix should not include .js
where: subject

2
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "data/gnome-shell-sass"]
path = data/gnome-shell-sass
url = https://git.gnome.org/browse/gnome-shell-sass/
url = https://gitlab.gnome.org/GNOME/gnome-shell-sass.git

31
HACKING
View File

@@ -1,31 +0,0 @@
--- Creating a New Extension ---
To create a new extension, add a subdirectory in extensions.
Then create a Makefile.am like the one in example, replacing
the EXTENSION_ID with the basename of your extension, which
must match the UUID in metadata.json.
If you need additional files, add them to EXTENSION_EXTRA.
Then modify extensions/Makefile.am and configure.ac. It should
be pretty self-explanatory.
Don't forget to add any translatable file to po/POTFILES.in, and
then you're done.
The Gettext domain you should choose is gnome-shell-extensions,
not gnome-shell, unless you're sure there is the string you
need in gnome-shell.
--- Coding Style ---
Generally, we follow GJS coding style (you can find it at
http://git.gnome.org/browse/gjs/tree/doc/Style_Guide.txt), which
in short is: indent 4 spaces, no tabs, space after comma, no space
after function call.
The Emacs mode line for this
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
Imports should be at the top, in two groups, one for standard
imports (like imports.lang or imports.dbus) and introspection,
the other for Shell API. Within the same group, put everything
in alphabetic order.

31
HACKING.md Normal file
View File

@@ -0,0 +1,31 @@
## Creating a New Extension
To create a new extension, add a subdirectory in extensions. Then create
a meson.build from the provided [template](extensions/meson.build.template).
If you need additional sources, add them to extension_sources. Similarily add
GSettings schemas to extension_schemas and other files to extension_data.
Then modify the [toplevel Meson file](meson.build) to add the new
extension name in the appropriate set (that is one of classic_extensions,
default_extensions or all_extensions).
Don't forget to add any translatable file to po/POTFILES.in, and
then you're done.
The Gettext domain you should choose is gnome-shell-extensions,
not gnome-shell, unless you're sure there is the string you
need in gnome-shell.
## Coding Style
Generally, we follow [GJS coding style][coding-style], which in short is:
indent 4 spaces, no tabs, space after comma, no space after function call.
The Emacs mode line for this
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
Imports should be at the top, in two groups, one for standard
imports (like imports.lang or imports.dbus) and introspection,
the other for Shell API. Within the same group, put everything
in alphabetic order.
[coding-style]: https://gitlab.gnome.org/GNOME/gjs/blob/HEAD/doc/Style_Guide.md

View File

@@ -1,52 +0,0 @@
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
DIST_SUBDIRS = data extensions po
SUBDIRS = extensions po
if CLASSIC_MODE
SUBDIRS += data
endif
EXTRA_DIST = lib/convenience.js
DISTCHECK_CONFIGURE_FLAGS = --enable-extensions=all
include include.mk
zip-file: all
-rm -fR $(builddir)/_build
-rm -fR $(builddir)/zip-files
$(MKDIR_P) $(builddir)/_build; \
$(MKDIR_P) $(builddir)/zip-files; \
$(MAKE) install DESTDIR="$(abs_builddir)/_build"; \
for i in $(ENABLED_EXTENSIONS); do \
mv "$(builddir)/_build$(topextensiondir)/$${i}$(extensionbase)" "$(builddir)/_build/"; \
cp -r "$(builddir)/_build$(datadir)/locale" "$(builddir)/_build/$${i}$(extensionbase)"; \
cp "$(srcdir)/COPYING" -t "$(builddir)/_build/$${i}$(extensionbase)"; \
cp "$(srcdir)/NEWS" -t "$(builddir)/_build/$${i}$(extensionbase)"; \
if [ -f "$(builddir)/_build$(datadir)/glib-2.0/schemas/$(gschemabase).$${i}.gschema.xml" ]; then \
$(MKDIR_P) "$(builddir)/_build/$${i}$(extensionbase)/schemas"; \
mv "$(builddir)/_build$(datadir)/glib-2.0/schemas/$(gschemabase).$${i}.gschema.xml" "$(builddir)/_build/$${i}$(extensionbase)/schemas"; \
glib-compile-schemas "$(builddir)/_build/$${i}$(extensionbase)/schemas"; \
fi; \
(cd "$(builddir)/_build/$${i}$(extensionbase)"; \
zip -qr "$(abs_builddir)/zip-files/$${i}$(extensionbase).shell-extension.zip" .; \
); \
done
-rm -fR $(builddir)/_build
localprefix = $(HOME)/.local/share/gnome-shell/extensions
local-install: zip-file
for i in $(ENABLED_EXTENSIONS); do \
uuid="$${i}$(extensionbase)"; \
zip_file="$(abs_builddir)/zip-files/$${uuid}.shell-extension.zip"; \
if [ -d "$(localprefix)/$${uuid}" ]; then \
rm -fR "$(localprefix)/$${uuid}"; \
fi; \
$(MKDIR_P) $(localprefix)/$${uuid}; \
(cd $(localprefix)/$${uuid}; \
unzip -q $${zip_file}; \
); \
done

511
NEWS
View File

@@ -1,3 +1,514 @@
42.alpha
========
* native-window-placement: Fix distorted layout in app grid [Sebastian; !189]
* window-list: Fix on-screen keyboard [Florian; !199]
* Misc. bug fixes and cleanups [Neal; Just; !195, !197]
Contributors:
Piotr Drąg, Neal Gompa, Sebastian Keller, Florian Müllner, Just Perfection
Translators:
Goran Vidović [hr], Sveinn í Felli [is], Yuri Chornoivan [uk],
Fabio Tomat [fur], Quentin PAGÈS [oc], Hugo Carvalho [pt],
Yaron Shahrabani [he], Jordi Mas i Hernandez [ca], MohammadSaleh Kamyab [fa],
Fran Dieguez [gl], Daniel Mustieles [es], Aleksandr Melman [ru],
Aurimas Černius [lt], Asier Sarasua Garmendia [eu], Kukuh Syafaat [id],
Rafael Fontenelle [pt_BR]
41.0
====
* Bump version
41.rc.1
=======
* Fix pre-generating stylesheets in tarball [Florian; !190]
Contributors:
Florian Müllner
41.rc
=====
* window-list: Adapt to overview-on-startup [Florian; !185]
* apps-menu: Use a custom 'toggle-menu' shortcut [Florian; !173]
* Misc. bug fixes and cleanups [Florian; !186]
Contributors:
Florian Müllner
41.beta
=======
* window-list: Extend reactive area of minimap to screen edges [Adam; !171]
* drive-menu: Improve detection of network mounts [Florian; !27, !176]
* Use distinct gettext domain for e.g.o uploads [Florian; #335]
* Misc. bug fixes and cleanups [Florian; !172, !174, !177, !167, !178, !180,
!181, !182, !183]
Contributors:
Marco Trevisan (Treviño), Adam Goode, Florian Müllner
Translators:
Hugo Carvalho [pt], Juliano de Souza Camargo [pt], Alexander Shopov [bg]
40.1
====
* Disable welcome dialog in classic session [Florian; !169]
* windowsNavigator: Adjust to a late gnome-shell change [Florian; !170]
Contributors:
Florian Müllner
Translators:
Ngọc Quân Trần [vi], Anders Jonsson [sv], Carmen Bianca BAKKER [eo],
Pawan Chitrakar [ne], Quentin PAGÈS [oc]
40.0
====
Translators:
Jiri Grönroos [fi]
40.rc
=====
* native-window-placement: Adjust to gnome-shell changes [Florian; !164]
* windows-navigator: Adjust to gnome-shell changes [Florian; !163]
* window-list, workspace-indicator: Only show previews for up to six workspaces
[Florian; !165]
* window-list, workspace-indicator: Improve workspace preview appearance
[Florian; !166]
Contributors:
Florian Müllner
Translators:
Fran Dieguez [gl]
40.beta
=======
* Add tooltips to workspace thumbnails [Florian; !155]
* Drop arrows from top bar menus [Florian; !156]
* drive-menu: Mark mounts that can be unmounted as removable [Michael; !152]
* Remove horizontal-workspaces extension [Florian; !158]
* Adjust to shell overview changes [Florian; !159, !160]
* Fix crashes [Daniel; !157]
* Misc. bug fixes and cleanups [Florian; !154, !161]
Contributors:
Michael Lawton, Florian Müllner, Daniel van Vugt
Translators:
Аляксей [be], A S Alam [pa]
40.alpha.1
==========
* Don't depend on sassc when building from tarball [Florian; !150]
* Port extensions preferences to GTK4 [Florian; !148]
* Misc. bug fixes and cleanups [Florian, Jonas; !149, !151, !153]
Contributors:
Jonas Dreßler, Florian Müllner
40.alpha
========
* window-list: Honor changes in skip-taskbar property [Sergio; !130]
* window-list, workspace-indicator: Adjust to 3.38 changes [Florian; !133]
* window-list, workspace-indicator: Improve previews in workspace thumbs
[Florian; #260, !142]
* auto-move: Improve behavior on multi-monitor setups [Florian; !135]
* windowNavigator: Adjust to 3.38 changes [Thun; #259]
* Misc. bug fixes and cleanups [Florian, Jonas Å, Jordan, Ray; !131, !136,
!137, !140, !141, !144, !146, !145]
Contributors:
Sergio Costas, Florian Müllner, Jordan Petridis, Thun Pin, Ray Strode,
Jonas Ådahl
Translators:
Fabio Tomat [fur], Jordi Mas [ca]
3.38.1
======
Contributors:
Yacine Bouklif, Florian Müllner
Translators:
Yacine Bouklif [kab], Cheng-Chia Tseng [zh_TW], Stas Solovey [ru],
Yosef Or Boczko [he]
3.38.0
======
Translators:
Balázs Meskó [hu], Alan Mortensen [da], Juliano Camargo [pt], Tim Sabsch [de],
Milo Casagrande [it], Rūdolfs Mazurs [lv]
3.37.92
=======
Translators:
Nathan Follens [nl], Zander Brown [en_GB], Aurimas Černius [lt],
Marek Černocký [cs], Changwoo Ryu [ko], Dušan Kazik [sk]
3.37.91
=======
Contributors:
Florian Müllner
Translators:
Fran Dieguez [gl], Akarshan Biswas [bn_IN], Kukuh Syafaat [id],
Piotr Drąg [pl], Rafael Fontenelle [pt_BR], Jiri Grönroos [fi],
Марко Костић [sr], Goran Vidović [hr]
3.37.90
=======
* Misc. bug fixes and cleanups [Florian, Piotr; !126, !128]
Contributors:
Piotr Drąg, Florian Müllner
Translators:
Fabio Tomat [fur], Efstathios Iosifidis [el], Anders Jonsson [sv],
Asier Sarasua Garmendia [eu], Alexandre Franke [fr]
3.37.3
======
* window-list, native-window-placement: Adjust to shell changes [Florian; !124]
Contributors:
Florian Müllner
Translators:
Jordi Mas [ca], sicklylife [ja], Boyuan Yang [zh_CN],
Baurzhan Muftakhidinov [kk]
3.37.2
======
* window-list, auto-move: Modernize preference dialogs [Florian; !121]
* Adjust to gnome-shell changes [Florian; !122]
Contributors:
Florian Müllner
Translators:
Cheng-Chia Tseng [zh_TW], Yuri Chornoivan [uk], Daniel Mustieles [es],
Emin Tufan Çetin [tr], Danial Behzadi [fa], Daniel Șerbănescu [ro],
Matej Urbančič [sl]
3.37.1
======
* drive-menu: Emphasize eject buttons [Florian; #223]
* user-theme: Add preference dialog [Florian; !117]
* window-list: Fix inconsistent state in preference dialog [Milan; !119]
* workspace-indicator: Overhaul preference dialog [Florian; !120]
* user-theme: Support session mode styles [Florian; !118]
* Misc. bug fixes and cleanups [Florian, Xiaoguang; !113, !106, !114, !116]
Contributors:
Milan Crha, Florian Müllner, Xiaoguang Wang
Translators:
Daniel Korostil [uk], Yosef Or Boczko [he], Kristjan SCHMIDT [eo],
Dz Chen [zh_CN], Danial Behzadi [fa], Yuri Chornoivan [uk],
Anders Jonsson [sv], Daniel Mustieles [es]
3.36.0
======
Contributors:
Florian Müllner
3.35.91
=======
Contributors:
Florian Müllner
Translators:
Zander Brown [en_GB]
3.35.90
=======
* Adjust to gnome-shell changes [Florian; !100, !101, !102]
* Force single-line window titles in window list [Florian; #202]
* Misc. bug fixes and cleanup [Florian; !104, !105]
Contributors:
Florian Müllner
Translators:
sicklylife [ja], Umarzuki Bin Mochlis Moktar [ms]
3.35.3
======
Translators:
Fran Dieguez [gl]
3.35.2
======
* Adjust to gnome-shell changes [Marco, Florian; !89, !95, !96]
* window-list, workspace-indicator: Exclude DESKTOP windows from previews
[Florian; !93]
* screenshot-window-sizer: Fix cycling through all valid sizes [Willy; !97]
Contributors:
Marco Trevisan (Treviño), Florian Müllner, Willy Stadnick
3.34.1
======
* Adjust to gnome-settings-daemon plugin removals [Xiaoguang; !94]
Contributors:
Florian Müllner, Xiaoguang Wang
Translators:
Nathan Follens [nl], Dušan Kazik [sk], Ask Hjorth Larsen [da],
Yi-Jyun Pan [zh_TW]
3.34.0
======
Translators:
Rafael Fontenelle [pt_BR], Efstathios Iosifidis [el], Milo Casagrande [it],
Sabri Ünal [tr]
3.33.92
=======
Translators:
Марко Костић [sr], Tim Sabsch [de], Rūdolfs Mazurs [lv], Matej Urbančič [sl],
Balázs Úr [hu], Claude Paroz [fr], Fran Dieguez [gl], Changwoo Ryu [ko],
Ryuta Fujii [ja], Fabio Tomat [fur], Goran Vidović [hr]
3.33.91
=======
* Misc. bug fixes and cleanups [Florian; !88, !90, !91, !92]
Contributors:
Florian Müllner
Translators:
Asier Sarasua Garmendia [eu], Anders Jonsson [sv], Marek Černocký [cs],
Kukuh Syafaat [id], Jiri Grönroos [fi], Florentina Mușat [ro],
Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl], Jordi Mas [ca],
Danial Behzadi [fa]
3.33.90
=======
* window-list: Support showing windows from all workspaces [Florian; #154]
* Misc. bug fixes and cleanups [Florian; !86, !87]
Contributors:
Florian Müllner
Translators:
Jor Teron [mjw]
3.33.4
======
* Make GNOME Classic more classic:
- Disable GNOME 3 overview [Florian; !69]
- Add window picker button to window list [Florian; !73, !80]
- Style improvements and fixes [Jakub; #169, !82]
- Support horizontal workspace layout in window list [Florian; !70]
- Add draggable previews to window list workspace switcher [Florian; !74]
- Arrange workspaces horizontally [Florian; !72]
* workspace-indicator: Support horizontal workspace layout [Florian; !71]
* workspace-indicator: Add draggable previews [Florian; !77]
* Misc. bug fixes and cleanups [Florian; !75, !76, !79, !78, #168, !84]
Contributors:
Florian Müllner, Jakub Steiner, Jor Teron
Translators:
Jor Teron [mjw]
3.33.3
======
* Misc. bug fixes [Florian, Marco; !67, !68]
Contributors:
Florian Müllner, Marco Trevisan (Treviño)
3.33.2
======
* Misc. bug fixes and cleanups [Florian; !66]
Contributors:
Florian Müllner
3.33.1
======
* Misc. bug fixes [Florian; !64]
Contributors:
Florian Müllner
3.32.1
======
* Fix windowsNavigator extension after ES6 port [Florian; #143]
* screenshot-window-sizer: Add phone screenshot sizes [Adrien; !65]
* Misc. bug fixes and cleanups [Fabian; !62]
Contributors:
Florian Müllner, Adrien Plazas, Fabian P. Schmidt
3.32.0
======
Contributors:
Florian Müllner
Translations:
Victor Ibragimov [tg], Kristjan SCHMIDT [eo], Mart Raudsepp [et]
3.31.92
=======
* Misc. bug fixes and cleanups [Florian; !57, !58, !59, !60]
Contributors:
Florian Müllner
3.31.91
=======
* apps-menu: Remove outdated legacy-tray handling [Florian; !53]
* user-theme: Allow using XDG user data dir [Tomasz; !55]
* Misc. bug fixes and cleanups [Florian; !52, !54, !56]
Contributors:
Tomasz Gąsior, Florian Müllner
Translators:
Matej Urbančič [sl], Gun Chleoc [gd]
3.31.90
=======
* Misc. bug fixes and cleanups [Florian; !49, !50, !51]
Contributors:
Florian Müllner
Translators:
Ryuta Fujii [ja], Charles Monzat [fr], Pieter Schalk Schoeman [af]
3.31.2
======
* Remove obsolete alternate-tab extension [Florian; #786496]
* Adjust to gnome-shell changes [Florian; #113]
Contributors:
Florian Müllner
3.30.1
======
* apps-menu: Fix height on HiDPI systems [Florian; #102]
* window-list: Only switch between windows on active workspace when scrolling
[Florian; #78]
Contributors:
Florian Müllner
3.30.0
======
* Bump version
3.29.91
=======
* Misc. bug fixes [Florian; #90]
Contributors:
Florian Müllner
3.29.90
=======
* Misc. bug fixes [Florian; #786496]
Contributors:
Florian Müllner
3.29.3
======
* Adjust to global.screen removal [Jonas; #759538]
Contributors:
Jonas Ådahl, Florian Müllner
3.29.2
======
* Misc. bug fixes [Florian; #69]
Contributors:
Florian Müllner
3.28.1
======
* Misc. bug fixes [Xiaoguang, Florian; #59, #62]
Contributors:
Florian Müllner, Xiaoguang Wang
Translators:
Dz Chen [zh_CN]
3.28.0
======
Contributors:
Florian Müllner, Xiaoguang Wang
Translators:
Aman Alam [pa], Bruce Cowan [en_GB]
3.27.92
=======
Contributors:
Florian Müllner
Translators:
Piotr Drąg [es], GNOME Translation Robot [gd], Daniel Șerbănescu [ro]
3.27.91
=======
* places-menu: Support unmounting ejectable places [Rémy; #17]
* apps-menu: Support separators and custom sort order [Florian; #27]
* Port to meson [Florian; #31, #45]
* window-list: Fix missing icons on wayland [Florian; #10]
* places-menu: Fix terminating gnome-shell with recent gjs [Florian; #44]
* auto-move: Make it work with wayland windows [Florian; #33]
* Classic theme fixes [Florian, Jonas; #26, #41, #39, #40]
* Require sassc for classic styling [Florian; !28]
* Misc. bug fixes [Piotr, Florian; #772211, #32, #30]
Contributors:
Jeremy Bicha, Piotr Drąg, Jonas Kümmerlin, Rémy Lefevre, Iñigo Martínez,
Florian Müllner
Translators:
Matej Urbančič [sl], Kjartan Maraas [nb]
3.27.1
======
* updated translations (ca@valencia)
3.26.1
======
* native-window-placement: Adjust to gnome-shell changes
* updated translations: el, fa, ru, sv
3.26.0
======
* updated translations (be, bg, ca, da, eu, fi, is, it, ko, lv, ml,
nl, pt_BR, vi, zh_TW)
3.25.91
=======
* updated translations (ca, fr, it, pl, pt_BR, sr, sr@latin, tr)
3.25.90
=======
* updated translations (es, gl, hr, hu, kk, sl, sv, sv)
3.25.4
======
* screenshot-window-sizer: Fix backward cycling

74
README
View File

@@ -1,74 +0,0 @@
GNOME Shell Extensions is a collection of extensions providing additional
and optional functionality to 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.
For more information about GNOME Shell Extensions
https://wiki.gnome.org/Projects/GnomeShell/Extensions
For general information about GNOME Shell
https://wiki.gnome.org/Projects/GnomeShell
Bugs should be reported at https://bugzilla.gnome.org against the 'gnome-shell'
product, with the 'extensions' component.
Extensions
==========
alternate-tab
Lets you use classic Alt+Tab (window-based instead of app-based) in GNOME Shell.
apps-menu
Lets you reach an application using gnome 2.x style menu on the panel.
auto-move-windows
Lets you manage your workspaces more easily, assigning a specific workspace to
each application as soon as it creates a window, in a manner configurable with a
GSettings key.
dock
Shows a dock-style task switcher on the right side of the screen.
drive-menu
Shows a status menu for rapid unmount and power off of external storage devices
(i.e. pendrives)
example
A minimal example illustrating how to write extensions.
gajim
Integration with Gajim, a Jabber/XMPP instant messaging client.
native-window-placement
An alternative algorithm for layouting the thumbnails in the windows overview, that
more closely reflects the actual positions and sizes.
places-menu
Shows a status Indicator for navigating to Places.
user-theme
Loads a shell theme from ~/.themes/<name>/gnome-shell.
windowsNavigator
Allow keyboard selection of windows and workspaces in overlay mode.
License
=======
GNOME Shell Extensions are distributed under the terms of the GNU General Public License,
version 2 or later. See the COPYING file for details.
Individual extensions may be licensed under different terms, see each source
file for details.

96
README.md Normal file
View File

@@ -0,0 +1,96 @@
# GNOME Shell Extensions
GNOME Shell Extensions is a collection of extensions providing additional
and optional functionality to 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.
The GNOME wiki has more information about [GNOME Shell Extensions][project-page],
as well as some general information about [GNOME Shell][shell-page].
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
## Extensions
* 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
Lets you reach an application using gnome 2.x style menu on the panel.
* auto-move-windows
Lets you manage your workspaces more easily, assigning a specific workspace to
each application as soon as it creates a window, in a manner configurable with a
GSettings key.
* drive-menu
Shows a status menu for rapid unmount and power off of external storage devices
(i.e. pendrives)
* launch-new-instance
Changes application icons to always launch a new instance when activated.
* native-window-placement
An alternative algorithm for layouting the thumbnails in the windows overview, that
more closely reflects the actual positions and sizes.
* places-menu
Shows a status Indicator for navigating to Places.
* screenshot-window-sizer
Adds a shortcut for resizing the focus window to a size that is suitable for GNOME Software screenshots
* user-theme
Loads a shell theme from ~/.themes/<name>/gnome-shell.
* window-list
Adds a bottom panel with a traditional window list.
* windowsNavigator
Allow keyboard selection of windows and workspaces in overlay mode.
* workspace-indicator
Adds a simple workspace switcher to the top bar.
## Default branch
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
GNOME Shell Extensions are distributed under the terms of the GNU General
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,26 +0,0 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
test -f $srcdir/configure.ac || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level gnome-shell-extensions directory"
exit 1
}
# Fetch submodules if needed
if test ! -f data/gnome-shell-sass/COPYING;
then
echo "+ Setting up submodules"
git submodule init
fi
git submodule update
which gnome-autogen.sh || {
echo "You need to install gnome-common from GNOME Git (or from"
echo "your OS vendor's package manager)."
exit 1
}
. gnome-autogen.sh

3
config/.gitignore vendored
View File

@@ -1,3 +0,0 @@
install-sh
mkinstalldirs
missing

View File

@@ -1,98 +0,0 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell-extensions],[3.25.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=extensions])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([config])
AM_INIT_AUTOMAKE([1.10 dist-xz no-dist-gzip foreign tar-ustar])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
GETTEXT_PACKAGE=gnome-shell-extensions
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
[The prefix for our gettext translation domains.])
AM_GNU_GETTEXT_VERSION([0.19.6])
AM_GNU_GETTEXT([external])
PKG_PROG_PKG_CONFIG([0.22])
GLIB_GSETTINGS
SHELL_VERSION="$PACKAGE_VERSION"
shell_major=`echo "$PACKAGE_VERSION" | cut -d'.' -f1`
shell_minor=`echo "$PACKAGE_VERSION" | cut -d'.' -f2`
if test "$(($shell_minor % 2))" -eq 0; then
SHELL_VERSION="$shell_major.$shell_minor"
fi
AC_SUBST([SHELL_VERSION])
dnl keep this in alphabetic order
CLASSIC_EXTENSIONS="apps-menu places-menu alternate-tab launch-new-instance window-list"
DEFAULT_EXTENSIONS="$CLASSIC_EXTENSIONS drive-menu screenshot-window-sizer windowsNavigator workspace-indicator"
ALL_EXTENSIONS="$DEFAULT_EXTENSIONS auto-move-windows example native-window-placement user-theme"
AC_SUBST(CLASSIC_EXTENSIONS, [$CLASSIC_EXTENSIONS])
AC_SUBST(ALL_EXTENSIONS, [$ALL_EXTENSIONS])
AC_ARG_ENABLE([extensions],
[AS_HELP_STRING([--enable-extensions],[Space separated list of extensions to enable.
The default is to build and distribute all extensions that can be installed in the home directory and have no external depedencies.
Use "all" to enable all available extensions, or "classic-mode" to enable extensions that restore GNOME 2 functionality.])],
[],
[enable_extensions=$DEFAULT_EXTENSIONS]
)
if test x"$enable_extensions" = xall; then
enable_extensions="$ALL_EXTENSIONS"
enable_classic_mode_default=yes
elif test x"$enable_extensions" = xclassic-mode; then
enable_extensions="$CLASSIC_EXTENSIONS"
enable_classic_mode_default=yes
else
enable_classic_mode_default=no
fi
AC_ARG_ENABLE([classic-mode],
[AS_HELP_STRING([--enable-classic-mode],[Enable installing data files for classic mode.
Defaults to yes if enabling all or classic-mode extensions, and no otherwise.])],
[],
[enable_classic_mode=$enable_classic_mode_default])
AM_CONDITIONAL([CLASSIC_MODE], [test x"$enable_classic_mode" != xno])
ENABLED_EXTENSIONS=
for e in $enable_extensions; do
case $e in
dnl keep this in alphabetic order
alternate-tab|apps-menu|auto-move-windows|drive-menu|example|launch-new-instance|native-window-placement|places-menu|screenshot-window-sizer|user-theme|window-list|windowsNavigator|workspace-indicator)
ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
;;
*)
AC_MSG_ERROR([invalid extension $e])
esac
done
AC_SUBST(ENABLED_EXTENSIONS, [$ENABLED_EXTENSIONS])
AC_PATH_PROG([SASSC],[sassc],[])
dnl Please keep this sorted alphabetically
AC_CONFIG_FILES([
data/Makefile
extensions/alternate-tab/Makefile
extensions/apps-menu/Makefile
extensions/auto-move-windows/Makefile
extensions/drive-menu/Makefile
extensions/example/Makefile
extensions/launch-new-instance/Makefile
extensions/native-window-placement/Makefile
extensions/places-menu/Makefile
extensions/screenshot-window-sizer/Makefile
extensions/user-theme/Makefile
extensions/window-list/Makefile
extensions/windowsNavigator/Makefile
extensions/workspace-indicator/Makefile
extensions/Makefile
Makefile
po/Makefile.in
])
AC_OUTPUT

View File

@@ -0,0 +1,9 @@
[org.gnome.mutter:GNOME-Classic]
dynamic-workspaces=false
[org.gnome.desktop.wm.preferences:GNOME-Classic]
button-layout='appmenu:minimize,maximize,close'
[org.gnome.desktop.wm.keybindings:GNOME-Classic]
switch-applications=[]
switch-windows=['<Super>Tab','<Alt>Tab']

View File

@@ -1,6 +1,2 @@
To generate the css files, from the project directory:
sassc -a gnome-classic.scss gnome-classic.css
To update the gnome-shell-sass submodule to latest upstream commit:
git submodule update --rebase

View File

@@ -1,73 +0,0 @@
include $(top_srcdir)/include.mk
sessiondir = $(datadir)/gnome-session/sessions
session_in_files = gnome-classic.session.desktop.in
session_DATA = $(session_in_files:.session.desktop.in=.session)
xsessiondir = $(datadir)/xsessions
xsession_in_files = gnome-classic.desktop.in
xsession_DATA = $(xsession_in_files:.desktop.in=.desktop)
modedir = $(datadir)/gnome-shell/modes
mode_in_files = classic.json.in
mode_DATA = $(mode_in_files:.json.in=.json)
themedir = $(datadir)/gnome-shell/theme
theme_DATA = \
$(srcdir)/calendar-today.svg \
$(srcdir)/classic-process-working.svg \
$(srcdir)/classic-toggle-off-intl.svg \
$(srcdir)/classic-toggle-off-us.svg \
$(srcdir)/classic-toggle-on-intl.svg \
$(srcdir)/classic-toggle-on-us.svg \
$(srcdir)/gnome-classic.css \
$(srcdir)/gnome-classic-high-contrast.css \
$(NULL)
theme_sources = \
$(srcdir)/gnome-classic.scss \
$(srcdir)/gnome-shell-sass/_colors.scss \
$(srcdir)/gnome-shell-sass/_common.scss \
$(srcdir)/gnome-shell-sass/_drawing.scss \
$(srcdir)/gnome-shell-sass/_high-contrast-colors.scss \
$(NULL)
%.css: %.scss $(theme_sources)
@if test -n "$(SASSC)"; then \
if $(AM_V_P); then PS4= set -x; else echo " GEN $@"; fi; \
$(SASSC) -a $< $@; \
fi
gsettings_SCHEMAS = org.gnome.shell.extensions.classic-overrides.gschema.xml
@GSETTINGS_RULES@
%.desktop:%.desktop.in
$(AM_V_GEN) $(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@
%.session: %.session.desktop.in
$(AM_V_GEN) $(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@
comma:=,
empty:=
space:= $(empty) $(empty)
extensions:=$(patsubst %,\"%$(extensionbase)\",$(CLASSIC_EXTENSIONS))
extension_list:=$(subst $(space),$(comma),$(extensions))
%.json:%.json.in
$(AM_V_GEN) sed \
-e "s|\@CLASSIC_EXTENSIONS\@|$(extension_list)|g" \
$< > $@
EXTRA_DIST = \
$(session_in_files) \
$(xsession_in_files) \
$(mode_in_files) \
$(gsettings_SCHEMAS) \
$(theme_DATA) \
$(NULL)
CLEANFILES = \
$(session_DATA) \
$(xsession_DATA) \
$(mode_DATA) \
$(NULL)

View File

@@ -1,8 +1,10 @@
{
"parentMode": "user",
"stylesheetName": "gnome-classic.css",
"hasOverview": false,
"showWelcomeDialog": false,
"enabledExtensions": [@CLASSIC_EXTENSIONS@],
"panel": { "left": ["activities", "appMenu"],
"panel": { "left": ["appMenu"],
"center": [],
"right": ["a11y", "keyboard", "dateMenu", "aggregateMenu"]
}

View File

@@ -0,0 +1,8 @@
[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

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,8 @@
[Desktop Entry]
Name=GNOME Classic
Comment=This session logs you into GNOME Classic
Exec=env GNOME_SHELL_SESSION_MODE=classic gnome-session --session 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

@@ -4,12 +4,13 @@ $variant: 'light';
@import "gnome-shell-sass/_colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";
@import "gnome-shell-sass/_widgets";
/* Overrides */
#panel {
#panel, #panel.solid {
font-weight: normal;
background-color: $bg_color !important;
background-color: $bg_color;
background-gradient-direction: vertical;
background-gradient-end: darken($bg_color,5%);
border-top-color: #666; /* we don't support non-uniform border-colors and
@@ -30,21 +31,39 @@ $variant: 'light';
-natural-hpadding: 8px;
-minimum-hpadding: 4px;
font-weight: normal;
color: $fg_color !important;
color: $fg_color;
text-shadow: none;
&:active, &:overview, &:focus, &:checked {
// Trick due to St limitations. It needs a background to draw
// a box-shadow
background-color: $selected_bg_color !important;
color: $selected_fg_color !important;
box-shadow: none;
& > .system-status-icon { icon-shadow: none; }
transition-duration: 0ms;
border: 0;
border-radius: 0px;
&.clock-display {
.clock {
transition-duration: 0ms;
border: 0;
border-radius: 0px;
}
}
&:hover {
color: lighten($fg_color,10%);
text-shadow: none;
& .system-status-icon { icon-shadow: none; }
}
&:active, &:overview, &:focus, &:checked {
// Trick due to St limitations. It needs a background to draw
// a box-shadow
background-color: $selected_bg_color;
color: $selected_fg_color;
box-shadow: none;
& > .system-status-icon { icon-shadow: none; }
}
.app-menu-icon { width: 0; height: 0; margin: 0; } // shell's display:none; :D
.system-status-icon {
icon-shadow: none;
}
}
.panel-corner,
@@ -56,18 +75,17 @@ $variant: 'light';
&.lock-screen,
&.unlock-screen,
&.login-screen {
background-color: transparentize($_bubble_bg_color, 0.5);
background-gradient-start: transparentize($_bubble_bg_color, 0.5);
background-gradient-end: transparentize($_bubble_bg_color, 0.5);
background-color: transparentize($bg_color, 0.5);
background-gradient-start: transparentize($bg_color, 0.5);
background-gradient-end: transparentize($bg_color, 0.5);
border-bottom: none;
.panel-button { color: $osd_fg_color; }
}
.popup-menu-arrow { width: 0; height: 0; } // shell's display: none;
}
#appMenu {
padding: 0 8px 0 8px;
spinner-image: url("classic-process-working.svg");
.panel-status-menu-box { padding: 0; }
}
.tile-preview-left.on-primary,
.tile-preview-right.on-primary,
@@ -86,3 +104,4 @@ $variant: 'light';
.calendar-day-with-events {
background-image: url("calendar-today.svg");
}

View File

@@ -1,3 +0,0 @@
[GNOME Session]
Name=GNOME Classic
RequiredComponents=org.gnome.Shell;org.gnome.SettingsDaemon.A11yKeyboard;org.gnome.SettingsDaemon.A11ySettings;org.gnome.SettingsDaemon.Clipboard;org.gnome.SettingsDaemon.Color;org.gnome.SettingsDaemon.Datetime;org.gnome.SettingsDaemon.Housekeeping;org.gnome.SettingsDaemon.Keyboard;org.gnome.SettingsDaemon.MediaKeys;org.gnome.SettingsDaemon.Mouse;org.gnome.SettingsDaemon.Power;org.gnome.SettingsDaemon.PrintNotifications;org.gnome.SettingsDaemon.Rfkill;org.gnome.SettingsDaemon.ScreensaverProxy;org.gnome.SettingsDaemon.Sharing;org.gnome.SettingsDaemon.Smartcard;org.gnome.SettingsDaemon.Sound;org.gnome.SettingsDaemon.Wacom;org.gnome.SettingsDaemon.XSettings;nautilus-classic;

119
data/meson.build Normal file
View File

@@ -0,0 +1,119 @@
session_desktop_base = 'gnome-classic'
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
classic_uuids += e + uuid_suffix
endforeach
mode_conf = configuration_data()
mode_conf.set('CLASSIC_EXTENSIONS', '"' + '", "'.join(classic_uuids) + '"')
mode_file = 'classic.json'
configure_file(
input: mode_file + '.in',
output: mode_file,
configuration: mode_conf,
install_dir: modedir
)
theme_sources = files(
'gnome-shell-sass/_colors.scss',
'gnome-shell-sass/_common.scss',
'gnome-shell-sass/_drawing.scss',
'gnome-shell-sass/_high-contrast-colors.scss',
'gnome-shell-sass/_widgets.scss',
'gnome-shell-sass/widgets/_a11y.scss',
'gnome-shell-sass/widgets/_app-grid.scss',
'gnome-shell-sass/widgets/_base.scss',
'gnome-shell-sass/widgets/_buttons.scss',
'gnome-shell-sass/widgets/_calendar.scss',
'gnome-shell-sass/widgets/_check-box.scss',
'gnome-shell-sass/widgets/_corner-ripple.scss',
'gnome-shell-sass/widgets/_dash.scss',
'gnome-shell-sass/widgets/_dialogs.scss',
'gnome-shell-sass/widgets/_entries.scss',
'gnome-shell-sass/widgets/_hotplug.scss',
'gnome-shell-sass/widgets/_ibus-popup.scss',
'gnome-shell-sass/widgets/_keyboard.scss',
'gnome-shell-sass/widgets/_login-dialog.scss',
'gnome-shell-sass/widgets/_looking-glass.scss',
'gnome-shell-sass/widgets/_message-list.scss',
'gnome-shell-sass/widgets/_misc.scss',
'gnome-shell-sass/widgets/_network-dialog.scss',
'gnome-shell-sass/widgets/_notifications.scss',
'gnome-shell-sass/widgets/_osd.scss',
'gnome-shell-sass/widgets/_overview.scss',
'gnome-shell-sass/widgets/_panel.scss',
'gnome-shell-sass/widgets/_popovers.scss',
'gnome-shell-sass/widgets/_screen-shield.scss',
'gnome-shell-sass/widgets/_scrollbars.scss',
'gnome-shell-sass/widgets/_search-entry.scss',
'gnome-shell-sass/widgets/_search-results.scss',
'gnome-shell-sass/widgets/_slider.scss',
'gnome-shell-sass/widgets/_switcher-popup.scss',
'gnome-shell-sass/widgets/_switches.scss',
'gnome-shell-sass/widgets/_tiled-previews.scss',
'gnome-shell-sass/widgets/_window-picker.scss',
'gnome-shell-sass/widgets/_workspace-switcher.scss',
'gnome-shell-sass/widgets/_workspace-thumbnails.scss'
)
theme_data = [
'calendar-today.svg',
'classic-process-working.svg',
'classic-toggle-off-intl.svg',
'classic-toggle-off-us.svg',
'classic-toggle-on-intl.svg',
'classic-toggle-on-us.svg',
'gnome-classic-high-contrast.css'
]
stylesheet = 'gnome-classic.css'
if fs.exists(stylesheet)
install_data(stylesheet, install_dir: themedir)
else
sassc = find_program('sassc', required: true)
custom_target(stylesheet,
input: fs.replace_suffix(stylesheet, '.scss'),
output: stylesheet,
depend_files: theme_sources,
command: [sassc, '-a', '@INPUT@', '@OUTPUT@'],
install: true,
install_dir: themedir
)
endif
install_data(theme_data, install_dir: themedir)
classic_override = '00_org.gnome.shell.extensions.classic.gschema.override'
install_data(classic_override, install_dir: schemadir)

View File

@@ -1,46 +0,0 @@
<schemalist>
<schema id="org.gnome.shell.extensions.classic-overrides"
path="/org/gnome/shell/extensions/classic-overrides/"
gettext-domain="gnome-shell-extensions">
<key name="attach-modal-dialogs" type="b">
<default>true</default>
<summary>Attach modal dialog to the parent window</summary>
<description>
This key overrides the key in org.gnome.mutter when running
GNOME Shell.
</description>
</key>
<key name="button-layout" type="s">
<default>"appmenu:minimize,maximize,close"</default>
<summary>Arrangement of buttons on the titlebar</summary>
<description>
This key overrides the key in org.gnome.desktop.wm.preferences when running GNOME Shell.
</description>
</key>
<key name="edge-tiling" type="b">
<default>true</default>
<summary>Enable edge tiling when dropping windows on screen edges</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
<key name="workspaces-only-on-primary" type="b">
<default>true</default>
<summary>Workspaces only on primary monitor</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
<key name="focus-change-on-pointer-rest" type="b">
<default>true</default>
<summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
</schema>
</schemalist>

47
export-zips.sh Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/sh
srcdir=`dirname $0`
srcdir=`(cd $srcdir && pwd)`
builddir=`mktemp -p $srcdir -d _build.XXXXXX` || exit 1
installdir=`mktemp -p $srcdir -d _install.XXXXXX` || exit 1
meson setup --prefix=$installdir -Dextension_set=all $srcdir $builddir
meson install -C $builddir
rm -rf $srcdir/zip-files
mkdir $srcdir/zip-files
extensiondir=$installdir/share/gnome-shell/extensions
schemadir=$installdir/share/glib-2.0/schemas
for f in $extensiondir/*; do
name=`basename ${f%%@*}`
uuid=$name@gnome-shell-extensions.gcampax.github.com
schema=$schemadir/org.gnome.shell.extensions.$name.gschema.xml
olddomain=gnome-shell-extensions
newdomain=gnome-shell-extension-$name
sed -i "/gettext-domain/ s:$olddomain:$newdomain:" $f/metadata.json
xgettext --from-code=UTF-8 --output-dir=$builddir --output=$name.pot $f/*.js
if [ -f $builddir/$name.pot ]; then
mkdir $f/po
for l in $(<$srcdir/po/LINGUAS); do
msgmerge --quiet --output-file=$f/po/$l.po \
$srcdir/po/$l.po $builddir/$name.pot
done
fi
cp $srcdir/NEWS $srcdir/COPYING $f
sources=(NEWS COPYING $(cd $f; ls *.js))
[ -f $schema ] || unset schema
gnome-extensions pack ${sources[@]/#/--extra-source=} \
${schema:+--schema=$schema} --out-dir=$srcdir/zip-files $f
done
rm -rf $builddir
rm -rf $installdir

View File

@@ -1,18 +0,0 @@
include $(top_srcdir)/include.mk
dist_extension_DATA = extension.js stylesheet.css $(EXTRA_MODULES)
nodist_extension_DATA = metadata.json $(top_srcdir)/lib/convenience.js $(EXTRA_EXTENSION)
EXTRA_DIST = metadata.json.in
metadata.json: metadata.json.in $(top_builddir)/config.status
$(AM_V_GEN) sed \
-e "s|[@]extension_id@|$(EXTENSION_ID)|" \
-e "s|[@]uuid@|$(uuid)|" \
-e "s|[@]gschemaname@|$(gschemaname)|" \
-e "s|[@]gettext_domain@|$(GETTEXT_PACKAGE)|" \
-e "s|[@]shell_current@|$(SHELL_VERSION)|" \
-e "s|[@]url@|$(extensionurl)|" \
$< > $@
CLEANFILES = metadata.json

0
extensions/.lock Normal file
View File

View File

@@ -1,3 +0,0 @@
DIST_SUBDIRS = $(ALL_EXTENSIONS)
SUBDIRS = $(ENABLED_EXTENSIONS)

View File

@@ -1,5 +0,0 @@
EXTENSION_ID = alternate-tab
EXTRA_MODULES = prefs.js
include ../../extension.mk

View File

@@ -1,59 +0,0 @@
/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const AltTab = imports.ui.altTab;
const Main = imports.ui.main;
const WindowManager = imports.ui.windowManager;
let injections = {};
function init(metadata) {
}
function setKeybinding(name, func) {
Main.wm.setCustomKeybindingHandler(name, Shell.ActionMode.NORMAL, func);
}
function enable() {
injections['_keyPressHandler'] = AltTab.WindowSwitcherPopup.prototype._keyPressHandler;
AltTab.WindowSwitcherPopup.prototype._keyPressHandler = function(keysym, action) {
switch(action) {
case Meta.KeyBindingAction.SWITCH_APPLICATIONS:
action = Meta.KeyBindingAction.SWITCH_WINDOWS;
break;
case Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD:
action = Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD;
break;
}
return injections['_keyPressHandler'].call(this, keysym, action);
};
Main.wm._forcedWindowSwitcher = function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.WindowSwitcherPopup();
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
tabPopup.destroy();
};
setKeybinding('switch-applications', Lang.bind(Main.wm, Main.wm._forcedWindowSwitcher));
setKeybinding('switch-applications-backward', Lang.bind(Main.wm, Main.wm._forcedWindowSwitcher));
}
function disable() {
var prop;
setKeybinding('switch-applications', Lang.bind(Main.wm, Main.wm._startSwitcher));
setKeybinding('switch-applications-backward', Lang.bind(Main.wm, Main.wm._startSwitcher));
for (prop in injections)
AltTab.WindowSwitcherPopup.prototype[prop] = injections[prop];
delete Main.wm._forcedWindowSwitcher;
}

View File

@@ -1,11 +0,0 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "AlternateTab",
"description": "Substitute Alt-Tab with a window based switcher that does not group by application.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME Bugzilla instead.",
"original-authors": [ "jw@bargsten.org", "thomas.bouffon@gmail.com" ],
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -1,85 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = function(e) { return e };
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const SETTINGS_APP_ICON_MODE = 'app-icon-mode';
const SETTINGS_CURRENT_WORKSPACE_ONLY = 'current-workspace-only';
const MODES = {
'thumbnail-only': N_("Thumbnail only"),
'app-icon-only': N_("Application icon only"),
'both': N_("Thumbnail and application icon"),
};
const AltTabSettingsWidget = new GObject.Class({
Name: 'AlternateTab.Prefs.AltTabSettingsWidget',
GTypeName: 'AltTabSettingsWidget',
Extends: Gtk.Grid,
_init : function(params) {
this.parent(params);
this.margin = 24;
this.row_spacing = 6;
this.orientation = Gtk.Orientation.VERTICAL;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
let presentLabel = '<b>' + _("Present windows as") + '</b>';
this.add(new Gtk.Label({ label: presentLabel, use_markup: true,
halign: Gtk.Align.START }));
let align = new Gtk.Alignment({ left_padding: 12 });
this.add(align);
let grid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
row_spacing: 6,
column_spacing: 6 });
align.add(grid);
let radio = null;
let currentMode = this._settings.get_string(SETTINGS_APP_ICON_MODE);
for (let mode in MODES) {
// copy the mode variable because it has function scope, not block scope
// so cannot be used in a closure
let modeCapture = mode;
let name = Gettext.gettext(MODES[mode]);
radio = new Gtk.RadioButton({ group: radio, label: name, valign: Gtk.Align.START });
radio.connect('toggled', Lang.bind(this, function(widget) {
if (widget.active)
this._settings.set_string(SETTINGS_APP_ICON_MODE, modeCapture);
}));
grid.add(radio);
if (mode == currentMode)
radio.active = true;
}
let check = new Gtk.CheckButton({ label: _("Show only windows in the current workspace"),
margin_top: 6 });
this._settings.bind(SETTINGS_CURRENT_WORKSPACE_ONLY, check, 'active', Gio.SettingsBindFlags.DEFAULT);
this.add(check);
},
});
function init() {
Convenience.initTranslations();
}
function buildPrefsWidget() {
let widget = new AltTabSettingsWidget();
widget.show_all();
return widget;
}

View File

@@ -1 +0,0 @@
/* This extensions requires no special styling */

View File

@@ -1,3 +0,0 @@
EXTENSION_ID = apps-menu
include ../../extension.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -1,9 +1,10 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Applications Menu",
"description": "Add a category-based menu for applications.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME Bugzilla instead.",
"description": "Add a category-based menu for applications.\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.",
"original-authors": [ "e2002@bk.ru", "debarshir@gnome.org" ],
"shell-version": [ "@shell_current@" ],
"url": "@url@"

View File

@@ -0,0 +1,12 @@
<schemalist gettext-domain="gnome-shell-extensions">
<schema id="org.gnome.shell.extensions.apps-menu"
path="/org/gnome/shell/extensions/apps-menu/">
<key name="apps-menu-toggle-menu" type="as">
<default>["&lt;Alt&gt;F1"]</default>
<summary>Keybinding to open the applications menu</summary>
<description>
Keybinding to open the applications menu.
</description>
</key>
</schema>
</schemalist>

View File

@@ -1,7 +0,0 @@
EXTENSION_ID = auto-move-windows
EXTRA_MODULES = prefs.js
include ../../extension.mk
include ../../settings.mk

View File

@@ -1,152 +1,142 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Start apps on custom workspaces
/* exported init enable disable */
const Glib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const { Shell } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const Main = imports.ui.main;
const SETTINGS_KEY = 'application-list';
class WindowMover {
constructor() {
this._settings = ExtensionUtils.getSettings();
this._appSystem = Shell.AppSystem.get_default();
this._appConfigs = new Map();
this._appData = new Map();
let settings;
this._appsChangedId =
this._appSystem.connect('installed-changed',
this._updateAppData.bind(this));
const WindowMover = new Lang.Class({
Name: 'AutoMoveWindows.WindowMover',
_init: function() {
this._settings = settings;
this._windowTracker = Shell.WindowTracker.get_default();
let display = global.screen.get_display();
// Connect after so the handler from ShellWindowTracker has already run
this._windowCreatedId = display.connect_after('window-created', Lang.bind(this, this._findAndMove));
},
destroy: function() {
if (this._windowCreatedId) {
global.screen.get_display().disconnect(this._windowCreatedId);
this._windowCreatedId = 0;
}
},
_ensureAtLeastWorkspaces: function(num, window) {
for (let j = global.screen.n_workspaces; j <= num; j++) {
window.change_workspace_by_index(j-1, false);
global.screen.append_new_workspace(false, 0);
}
},
_findAndMove: function(display, window, noRecurse) {
if (window.skip_taskbar)
return;
let spaces = this._settings.get_strv(SETTINGS_KEY);
let app = this._windowTracker.get_window_app(window);
if (!app) {
if (!noRecurse) {
// window is not tracked yet
Mainloop.idle_add(Lang.bind(this, function() {
this._findAndMove(display, window, true);
return false;
}));
} else
log ('Cannot find application for window');
return;
}
let app_id = app.get_id();
for ( let j = 0 ; j < spaces.length; j++ ) {
let apps_to_space = spaces[j].split(":");
// Match application id
if (apps_to_space[0] == app_id) {
let workspace_num = parseInt(apps_to_space[1]) - 1;
if (workspace_num >= global.screen.n_workspaces)
this._ensureAtLeastWorkspaces(workspace_num, window);
window.change_workspace_by_index(workspace_num, false);
}
}
this._settings.connect('changed', this._updateAppConfigs.bind(this));
this._updateAppConfigs();
}
});
_updateAppConfigs() {
this._appConfigs.clear();
this._settings.get_strv('application-list').forEach(v => {
let [appId, num] = v.split(':');
this._appConfigs.set(appId, parseInt(num) - 1);
});
this._updateAppData();
}
_updateAppData() {
let ids = [...this._appConfigs.keys()];
let removedApps = [...this._appData.keys()]
.filter(a => !ids.includes(a.id));
removedApps.forEach(app => {
app.disconnect(this._appData.get(app).windowsChangedId);
this._appData.delete(app);
});
let addedApps = ids
.map(id => this._appSystem.lookup_app(id))
.filter(app => app && !this._appData.has(app));
addedApps.forEach(app => {
let data = {
windowsChangedId: app.connect('windows-changed',
this._appWindowsChanged.bind(this)),
moveWindowsId: 0,
windows: app.get_windows(),
};
this._appData.set(app, data);
});
}
destroy() {
if (this._appsChangedId) {
this._appSystem.disconnect(this._appsChangedId);
this._appsChangedId = 0;
}
if (this._settings) {
this._settings.run_dispose();
this._settings = null;
}
this._appConfigs.clear();
this._updateAppData();
}
_moveWindow(window, workspaceNum) {
if (window.skip_taskbar || window.is_on_all_workspaces())
return;
// ensure we have the required number of workspaces
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);
}
window.change_workspace_by_index(workspaceNum, false);
}
_appWindowsChanged(app) {
let data = this._appData.get(app);
let windows = app.get_windows();
// If get_compositor_private() returns non-NULL on a removed windows,
// the window still exists and is just moved to a different workspace
// or something; assume it'll be added back immediately, so keep it
// to avoid moving it again
windows.push(...data.windows.filter(w => {
return !windows.includes(w) && w.get_compositor_private() !== null;
}));
let workspaceNum = this._appConfigs.get(app.id);
windows.filter(w => !data.windows.includes(w)).forEach(window => {
this._moveWindow(window, workspaceNum);
});
data.windows = windows;
}
}
let prevCheckWorkspaces;
let winMover;
/** */
function init() {
Convenience.initTranslations();
settings = Convenience.getSettings();
ExtensionUtils.initTranslations();
}
/**
* @returns {bool} - false (used as MetaLater handler)
*/
function myCheckWorkspaces() {
let i;
let emptyWorkspaces = new Array(this._workspaces.length);
if (!Meta.prefs_get_dynamic_workspaces()) {
this._checkWorkspacesId = 0;
return false;
let keepAliveWorkspaces = [];
let foundNonEmpty = false;
for (let i = this._workspaces.length - 1; i >= 0; i--) {
if (!foundNonEmpty) {
foundNonEmpty = this._workspaces[i].list_windows().some(
w => !w.is_on_all_workspaces());
} else if (!this._workspaces[i]._keepAliveId) {
keepAliveWorkspaces.push(this._workspaces[i]);
}
}
for (i = 0; i < this._workspaces.length; i++) {
let lastRemoved = this._workspaces[i]._lastRemovedWindow;
if ((lastRemoved &&
(lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN ||
lastRemoved.get_window_type() == Meta.WindowType.DIALOG ||
lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG)) ||
this._workspaces[i]._keepAliveId)
emptyWorkspaces[i] = false;
else
emptyWorkspaces[i] = true;
}
// make sure the original method only removes empty workspaces at the end
keepAliveWorkspaces.forEach(ws => (ws._keepAliveId = 1));
prevCheckWorkspaces.call(this);
keepAliveWorkspaces.forEach(ws => delete ws._keepAliveId);
let sequences = Shell.WindowTracker.get_default().get_startup_sequences();
for (i = 0; i < sequences.length; i++) {
let index = sequences[i].get_workspace();
if (index >= 0 && index <= global.screen.n_workspaces)
emptyWorkspaces[index] = false;
}
let windows = global.get_window_actors();
for (i = 0; i < windows.length; i++) {
let winActor = windows[i];
let win = winActor.meta_window;
if (win.is_on_all_workspaces())
continue;
let workspaceIndex = win.get_workspace().index();
emptyWorkspaces[workspaceIndex] = false;
}
// If we don't have an empty workspace at the end, add one
if (!emptyWorkspaces[emptyWorkspaces.length -1]) {
global.screen.append_new_workspace(false, global.get_current_time());
emptyWorkspaces.push(false);
}
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
emptyWorkspaces[activeWorkspaceIndex] = false;
// Delete other empty workspaces; do it from the end to avoid index changes
for (i = emptyWorkspaces.length - 2; i >= 0; i--) {
if (emptyWorkspaces[i])
global.screen.remove_workspace(this._workspaces[i], global.get_current_time());
else
break;
}
this._checkWorkspacesId = 0;
return false;
}
/** */
function enable() {
prevCheckWorkspaces = Main.wm._workspaceTracker._checkWorkspaces;
Main.wm._workspaceTracker._checkWorkspaces = myCheckWorkspaces;
@@ -154,6 +144,7 @@ function enable() {
winMover = new WindowMover();
}
/** */
function disable() {
Main.wm._workspaceTracker._checkWorkspaces = prevCheckWorkspaces;
winMover.destroy();

View File

@@ -0,0 +1,8 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('prefs.js')
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -1,274 +1,278 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Start apps on custom workspaces
/* exported init buildPrefsWidget */
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const GMenu = imports.gi.GMenu;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = function(e) { return e };
const { Gio, GLib, GObject, Gtk, Pango } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _ = ExtensionUtils.gettext;
const SETTINGS_KEY = 'application-list';
const WORKSPACE_MAX = 36; // compiled in limit of mutter
const Columns = {
APPINFO: 0,
DISPLAY_NAME: 1,
ICON: 2,
WORKSPACE: 3,
ADJUSTMENT: 4
};
const AutoMoveSettingsWidget = GObject.registerClass(
class AutoMoveSettingsWidget extends Gtk.ScrolledWindow {
_init() {
super._init({
hscrollbar_policy: Gtk.PolicyType.NEVER,
});
const Widget = new GObject.Class({
Name: 'AutoMoveWindows.Prefs.Widget',
GTypeName: 'AutoMoveWindowsPrefsWidget',
Extends: Gtk.Grid,
const box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
halign: Gtk.Align.CENTER,
spacing: 12,
margin_top: 36,
margin_bottom: 36,
margin_start: 36,
margin_end: 36,
});
this.set_child(box);
_init: function(params) {
this.parent(params);
this.set_orientation(Gtk.Orientation.VERTICAL);
box.append(new Gtk.Label({
label: '<b>%s</b>'.format(_('Workspace Rules')),
use_markup: true,
halign: Gtk.Align.START,
}));
this._settings = Convenience.getSettings();
this._settings.connect('changed', Lang.bind(this, this._refresh));
this._changedPermitted = false;
this._list = new Gtk.ListBox({
selection_mode: Gtk.SelectionMode.NONE,
valign: Gtk.Align.START,
show_separators: true,
});
box.append(this._list);
this._store = new Gtk.ListStore();
this._store.set_column_types([Gio.AppInfo, GObject.TYPE_STRING, Gio.Icon, GObject.TYPE_INT,
Gtk.Adjustment]);
const context = this._list.get_style_context();
const cssProvider = new Gtk.CssProvider();
cssProvider.load_from_data(
'list { min-width: 30em; }');
let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN});
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.add(scrolled);
context.add_provider(cssProvider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
context.add_class('frame');
this._list.append(new NewRuleRow());
this._treeView = new Gtk.TreeView({ model: this._store,
hexpand: true, vexpand: true });
this._treeView.get_selection().set_mode(Gtk.SelectionMode.SINGLE);
this._actionGroup = new Gio.SimpleActionGroup();
this._list.insert_action_group('rules', this._actionGroup);
let appColumn = new Gtk.TreeViewColumn({ expand: true, sort_column_id: Columns.DISPLAY_NAME,
title: _("Application") });
let iconRenderer = new Gtk.CellRendererPixbuf;
appColumn.pack_start(iconRenderer, false);
appColumn.add_attribute(iconRenderer, "gicon", Columns.ICON);
let nameRenderer = new Gtk.CellRendererText;
appColumn.pack_start(nameRenderer, true);
appColumn.add_attribute(nameRenderer, "text", Columns.DISPLAY_NAME);
this._treeView.append_column(appColumn);
let action;
action = new Gio.SimpleAction({ name: 'add' });
action.connect('activate', this._onAddActivated.bind(this));
this._actionGroup.add_action(action);
let workspaceColumn = new Gtk.TreeViewColumn({ title: _("Workspace"),
sort_column_id: Columns.WORKSPACE });
let workspaceRenderer = new Gtk.CellRendererSpin({ editable: true });
workspaceRenderer.connect('edited', Lang.bind(this, this._workspaceEdited));
workspaceColumn.pack_start(workspaceRenderer, true);
workspaceColumn.add_attribute(workspaceRenderer, "adjustment", Columns.ADJUSTMENT);
workspaceColumn.add_attribute(workspaceRenderer, "text", Columns.WORKSPACE);
this._treeView.append_column(workspaceColumn);
action = new Gio.SimpleAction({
name: 'remove',
parameter_type: new GLib.VariantType('s'),
});
action.connect('activate', this._onRemoveActivated.bind(this));
this._actionGroup.add_action(action);
scrolled.add(this._treeView);
action = new Gio.SimpleAction({ name: 'update' });
action.connect('activate', () => {
this._settings.set_strv(SETTINGS_KEY,
this._getRuleRows().map(row => `${row.id}:${row.value}`));
});
this._actionGroup.add_action(action);
this._updateAction = action;
let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR });
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
this.add(toolbar);
this._settings = ExtensionUtils.getSettings();
this._changedId = this._settings.connect('changed',
this._sync.bind(this));
this._sync();
let newButton = new Gtk.ToolButton({ icon_name: 'bookmark-new-symbolic',
label: _("Add Rule"),
is_important: true });
newButton.connect('clicked', Lang.bind(this, this._createNew));
toolbar.add(newButton);
this.connect('destroy', () => this._settings.run_dispose());
}
let delButton = new Gtk.ToolButton({ icon_name: 'edit-delete-symbolic' });
delButton.connect('clicked', Lang.bind(this, this._deleteSelected));
toolbar.add(delButton);
let selection = this._treeView.get_selection();
selection.connect('changed',
function() {
delButton.sensitive = selection.count_selected_rows() > 0;
});
delButton.sensitive = selection.count_selected_rows() > 0;
this._changedPermitted = true;
this._refresh();
},
_createNew: function() {
let dialog = new Gtk.Dialog({ title: _("Create new matching rule"),
transient_for: this.get_toplevel(),
use_header_bar: true,
modal: true });
dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
let addButton = dialog.add_button(_("Add"), Gtk.ResponseType.OK);
dialog.set_default_response(Gtk.ResponseType.OK);
let grid = new Gtk.Grid({ column_spacing: 10,
row_spacing: 15,
margin: 10 });
dialog._appChooser = new Gtk.AppChooserWidget({ show_all: true });
dialog._appChooser.connect('application-selected', Lang.bind(this,
function(w, appInfo) {
addButton.sensitive = appInfo &&
this._checkId(appInfo.get_id());
}));
let appInfo = dialog._appChooser.get_app_info();
addButton.sensitive = appInfo && this._checkId(appInfo.get_id());
grid.attach(dialog._appChooser, 0, 0, 2, 1);
grid.attach(new Gtk.Label({ label: _("Workspace"),
halign: Gtk.Align.END }), 0, 1, 1, 1);
let adjustment = new Gtk.Adjustment({ lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1
});
dialog._spin = new Gtk.SpinButton({ adjustment: adjustment,
snap_to_ticks: true });
dialog._spin.set_value(1);
grid.attach(dialog._spin, 1, 1, 1, 1);
dialog.get_content_area().add(grid);
dialog.connect('response', Lang.bind(this, function(dialog, id) {
if (id != Gtk.ResponseType.OK) {
dialog.destroy();
return;
_onAddActivated() {
const dialog = new NewRuleDialog(this.get_root());
dialog.connect('response', (dlg, id) => {
const appInfo = id === Gtk.ResponseType.OK
? dialog.get_widget().get_app_info() : null;
if (appInfo) {
this._settings.set_strv(SETTINGS_KEY, [
...this._settings.get_strv(SETTINGS_KEY),
`${appInfo.get_id()}:1`,
]);
}
let appInfo = dialog._appChooser.get_app_info();
if (!appInfo)
return;
let index = Math.floor(dialog._spin.value);
if (isNaN(index) || index < 0)
index = 1;
this._changedPermitted = false;
this._appendItem(appInfo.get_id(), index);
this._changedPermitted = true;
let iter = this._store.append();
let adj = new Gtk.Adjustment({ lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
value: index });
this._store.set(iter,
[Columns.APPINFO, Columns.ICON, Columns.DISPLAY_NAME, Columns.WORKSPACE, Columns.ADJUSTMENT],
[appInfo, appInfo.get_icon(), appInfo.get_display_name(), index, adj]);
dialog.destroy();
}));
dialog.show_all();
},
});
dialog.show();
}
_deleteSelected: function() {
let [any, model, iter] = this._treeView.get_selection().get_selected();
_onRemoveActivated(action, param) {
const removed = param.deepUnpack();
this._settings.set_strv(SETTINGS_KEY,
this._settings.get_strv(SETTINGS_KEY).filter(entry => {
const [id] = entry.split(':');
return id !== removed;
}));
}
if (any) {
let appInfo = this._store.get_value(iter, Columns.APPINFO);
_getRuleRows() {
return [...this._list].filter(row => !!row.id);
}
this._changedPermitted = false;
this._removeItem(appInfo.get_id());
this._changedPermitted = true;
this._store.remove(iter);
}
},
_sync() {
const oldRules = this._getRuleRows();
const newRules = this._settings.get_strv(SETTINGS_KEY).map(entry => {
const [id, value] = entry.split(':');
return { id, value };
});
_workspaceEdited: function(renderer, pathString, text) {
let index = parseInt(text);
if (isNaN(index) || index < 0)
index = 1;
let path = Gtk.TreePath.new_from_string(pathString);
let [model, iter] = this._store.get_iter(path);
let appInfo = this._store.get_value(iter, Columns.APPINFO);
this._settings.block_signal_handler(this._changedId);
this._updateAction.enabled = false;
this._changedPermitted = false;
this._changeItem(appInfo.get_id(), index);
this._store.set_value(iter, Columns.WORKSPACE, index);
this._changedPermitted = true;
},
newRules.forEach(({ id, value }, index) => {
const row = oldRules.find(r => r.id === id);
const appInfo = row
? null : Gio.DesktopAppInfo.new(id);
_refresh: function() {
if (!this._changedPermitted)
// Ignore this notification, model is being modified outside
return;
if (row)
row.set({ value });
else if (appInfo)
this._list.insert(new RuleRow(appInfo, value), index);
});
this._store.clear();
const removed = oldRules.filter(
({ id }) => !newRules.find(r => r.id === id));
removed.forEach(r => this._list.remove(r));
let currentItems = this._settings.get_strv(SETTINGS_KEY);
let validItems = [ ];
for (let i = 0; i < currentItems.length; i++) {
let [id, index] = currentItems[i].split(':');
let appInfo = Gio.DesktopAppInfo.new(id);
if (!appInfo)
continue;
validItems.push(currentItems[i]);
let iter = this._store.append();
let adj = new Gtk.Adjustment({ lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
value: index });
this._store.set(iter,
[Columns.APPINFO, Columns.ICON, Columns.DISPLAY_NAME, Columns.WORKSPACE, Columns.ADJUSTMENT],
[appInfo, appInfo.get_icon(), appInfo.get_display_name(), parseInt(index), adj]);
}
if (validItems.length != currentItems.length) // some items were filtered out
this._settings.set_strv(SETTINGS_KEY, validItems);
},
_checkId: function(id) {
let items = this._settings.get_strv(SETTINGS_KEY);
return !items.some(function(i) { return i.startsWith(id + ':'); });
},
_appendItem: function(id, workspace) {
let currentItems = this._settings.get_strv(SETTINGS_KEY);
currentItems.push(id + ':' + workspace);
this._settings.set_strv(SETTINGS_KEY, currentItems);
},
_removeItem: function(id) {
let currentItems = this._settings.get_strv(SETTINGS_KEY);
let index = currentItems.map(function(el) {
return el.split(':')[0];
}).indexOf(id);
if (index < 0)
return;
currentItems.splice(index, 1);
this._settings.set_strv(SETTINGS_KEY, currentItems);
},
_changeItem: function(id, workspace) {
let currentItems = this._settings.get_strv(SETTINGS_KEY);
let index = currentItems.map(function(el) {
return el.split(':')[0];
}).indexOf(id);
if (index < 0)
currentItems.push(id + ':' + workspace);
else
currentItems[index] = id + ':' + workspace;
this._settings.set_strv(SETTINGS_KEY, currentItems);
this._settings.unblock_signal_handler(this._changedId);
this._updateAction.enabled = true;
}
});
const RuleRow = GObject.registerClass({
Properties: {
'id': GObject.ParamSpec.string(
'id', 'id', 'id',
GObject.ParamFlags.READABLE,
''),
'value': GObject.ParamSpec.uint(
'value', 'value', 'value',
GObject.ParamFlags.READWRITE,
1, WORKSPACE_MAX, 1),
},
}, class RuleRow extends Gtk.ListBoxRow {
_init(appInfo, value) {
const box = new Gtk.Box({
spacing: 6,
margin_top: 6,
margin_bottom: 6,
margin_start: 6,
margin_end: 6,
});
super._init({
activatable: false,
value,
child: box,
});
this._appInfo = appInfo;
const icon = new Gtk.Image({
gicon: appInfo.get_icon(),
pixel_size: 32,
});
icon.get_style_context().add_class('icon-dropshadow');
box.append(icon);
const label = new Gtk.Label({
label: appInfo.get_display_name(),
halign: Gtk.Align.START,
hexpand: true,
max_width_chars: 20,
ellipsize: Pango.EllipsizeMode.END,
});
box.append(label);
const spinButton = new Gtk.SpinButton({
adjustment: new Gtk.Adjustment({
lower: 1,
upper: WORKSPACE_MAX,
step_increment: 1,
}),
snap_to_ticks: true,
margin_end: 6,
});
this.bind_property('value',
spinButton, 'value',
GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
box.append(spinButton);
const button = new Gtk.Button({
action_name: 'rules.remove',
action_target: new GLib.Variant('s', this.id),
icon_name: 'edit-delete-symbolic',
});
box.append(button);
this.connect('notify::value',
() => this.activate_action('rules.update', null));
}
get id() {
return this._appInfo.get_id();
}
});
const NewRuleRow = GObject.registerClass(
class NewRuleRow extends Gtk.ListBoxRow {
_init() {
super._init({
action_name: 'rules.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 Rule')]);
}
});
const NewRuleDialog = GObject.registerClass(
class NewRuleDialog extends Gtk.AppChooserDialog {
_init(parent) {
super._init({
transient_for: parent,
modal: true,
});
this._settings = ExtensionUtils.getSettings();
this.get_widget().set({
show_all: true,
show_other: true, // hide more button
});
this.get_widget().connect('application-selected',
this._updateSensitivity.bind(this));
this._updateSensitivity();
}
_updateSensitivity() {
const rules = this._settings.get_strv(SETTINGS_KEY);
const appInfo = this.get_widget().get_app_info();
this.set_response_sensitive(Gtk.ResponseType.OK,
appInfo && !rules.some(i => i.startsWith(appInfo.get_id())));
}
});
/** */
function init() {
Convenience.initTranslations();
ExtensionUtils.initTranslations();
}
/**
* @returns {Gtk.Widget} - the prefs widget
*/
function buildPrefsWidget() {
let widget = new Widget({ margin: 12 });
widget.show_all();
return widget;
return new AutoMoveSettingsWidget();
}

View File

@@ -1,3 +0,0 @@
EXTENSION_ID = drive-menu
include ../../extension.mk

View File

@@ -1,56 +1,75 @@
/* exported init enable disable */
// Drive menu extension
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const { Clutter, Gio, GObject, Shell, St } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const ShellMountOperation = imports.ui.shellMountOperation;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _ = ExtensionUtils.gettext;
const MountMenuItem = new Lang.Class({
Name: 'DriveMenu.MountMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
var MountMenuItem = GObject.registerClass(
class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(mount) {
super._init({
style_class: 'drive-menu-item',
});
_init: function(mount) {
this.parent();
this.label = new St.Label({
text: mount.get_name(),
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
this.add_child(this.label);
this.label_actor = this.label;
this.label = new St.Label({ text: mount.get_name() });
this.actor.add(this.label, { expand: true });
this.actor.label_actor = this.label;
this.mount = mount;
this.mount = mount;
this.connect('destroy', this._onDestroy.bind(this));
let ejectIcon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon ' });
let ejectButton = new St.Button({ child: ejectIcon });
ejectButton.connect('clicked', Lang.bind(this, this._eject));
this.actor.add(ejectButton);
let ejectIcon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon',
});
let ejectButton = new St.Button({
child: ejectIcon,
style_class: 'button',
});
ejectButton.connect('clicked', this._eject.bind(this));
this.add(ejectButton);
this._changedId = mount.connect('changed', Lang.bind(this, this._syncVisibility));
this.hide();
this._changedId = mount.connect('changed', this._syncVisibility.bind(this));
this._syncVisibility();
},
}
destroy: function() {
_onDestroy() {
if (this._changedId) {
this.mount.disconnect(this._changedId);
this._changedId = 0;
}
this.parent();
},
super.destroy();
}
_isInteresting: function() {
_fsIsRemote(root) {
return new Promise((resolve, reject) => {
const attr = Gio.FILE_ATTRIBUTE_FILESYSTEM_REMOTE;
root.query_filesystem_info_async(attr, null, (o, res) => {
try {
const info = root.query_filesystem_info_finish(res);
resolve(!info.get_attribute_boolean(attr));
} catch (e) {
reject(e);
}
});
});
}
async _isInteresting() {
if (!this.mount.can_eject() && !this.mount.can_unmount())
return false;
if (this.mount.is_shadowed())
@@ -58,151 +77,159 @@ const MountMenuItem = new Lang.Class({
let volume = this.mount.get_volume();
if (volume == null) {
// probably a GDaemonMount, could be network or
// local, but we can't tell; assume it's local for now
return true;
if (volume)
return volume.get_identifier('class') !== 'network';
const root = this.mount.get_root();
try {
return await this._fsIsRemote(root);
} catch (e) {
log(`Failed to query filesystem: ${e.message}`);
}
return volume.get_identifier('class') != 'network';
},
// Hack, fall back to looking at GType
return Gio._LocalFilePrototype.isPrototypeOf(root);
}
_syncVisibility: function() {
this.actor.visible = this._isInteresting();
},
async _syncVisibility() {
this.visible = await this._isInteresting();
}
_eject: function() {
let mountOp = new ShellMountOperation.ShellMountOperation(this.mount);
_eject() {
let unmountArgs = [
Gio.MountUnmountFlags.NONE,
new ShellMountOperation.ShellMountOperation(this.mount).mountOp,
null, // Gio.Cancellable
];
if (this.mount.can_eject())
this.mount.eject_with_operation(Gio.MountUnmountFlags.NONE,
mountOp.mountOp,
null, // Gio.Cancellable
Lang.bind(this, this._ejectFinish));
else
this.mount.unmount_with_operation(Gio.MountUnmountFlags.NONE,
mountOp.mountOp,
null, // Gio.Cancellable
Lang.bind(this, this._unmountFinish));
},
if (this.mount.can_eject()) {
this.mount.eject_with_operation(...unmountArgs,
this._ejectFinish.bind(this));
} else {
this.mount.unmount_with_operation(...unmountArgs,
this._unmountFinish.bind(this));
}
}
_unmountFinish: function(mount, result) {
try {
mount.unmount_with_operation_finish(result);
} catch(e) {
this._reportFailure(e);
}
},
_unmountFinish(mount, result) {
try {
mount.unmount_with_operation_finish(result);
} catch (e) {
this._reportFailure(e);
}
}
_ejectFinish: function(mount, result) {
try {
mount.eject_with_operation_finish(result);
} catch(e) {
this._reportFailure(e);
}
},
_ejectFinish(mount, result) {
try {
mount.eject_with_operation_finish(result);
} catch (e) {
this._reportFailure(e);
}
}
_reportFailure: function(exception) {
let msg = _("Ejecting drive “%s” failed:").format(this.mount.get_name());
Main.notifyError(msg, exception.message);
},
_reportFailure(exception) {
// TRANSLATORS: %s is the filesystem name
let msg = _('Ejecting drive “%s” failed:').format(this.mount.get_name());
Main.notifyError(msg, exception.message);
}
activate: function(event) {
activate(event) {
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(this.mount.get_root().get_uri(),
context);
Gio.AppInfo.launch_default_for_uri(uri, context);
this.parent(event);
super.activate(event);
}
});
const DriveMenu = new Lang.Class({
Name: 'DriveMenu.DriveMenu',
Extends: PanelMenu.Button,
let DriveMenu = GObject.registerClass(
class DriveMenu extends PanelMenu.Button {
_init() {
super._init(0.0, _('Removable devices'));
_init: function() {
this.parent(0.0, _("Removable devices"));
let icon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'system-status-icon',
});
let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
let icon = new St.Icon({ icon_name: 'media-eject-symbolic',
style_class: 'system-status-icon' });
this.add_child(icon);
hbox.add_child(icon);
hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.actor.add_child(hbox);
this._monitor = Gio.VolumeMonitor.get();
this._addedId = this._monitor.connect('mount-added',
(monitor, mount) => this._addMount(mount));
this._removedId = this._monitor.connect('mount-removed', (monitor, mount) => {
this._removeMount(mount);
this._updateMenuVisibility();
});
this._monitor = Gio.VolumeMonitor.get();
this._addedId = this._monitor.connect('mount-added', Lang.bind(this, function(monitor, mount) {
this._addMount(mount);
this._updateMenuVisibility();
}));
this._removedId = this._monitor.connect('mount-removed', Lang.bind(this, function(monitor, mount) {
this._removeMount(mount);
this._updateMenuVisibility();
}));
this._mounts = [];
this._mounts = [ ];
this._monitor.get_mounts().forEach(this._addMount.bind(this));
this._monitor.get_mounts().forEach(Lang.bind(this, this._addMount));
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_('Open Files'), event => {
let appSystem = Shell.AppSystem.get_default();
let app = appSystem.lookup_app('org.gnome.Nautilus.desktop');
app.activate_full(-1, event.get_time());
});
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Open Files"), function(event) {
let appSystem = Shell.AppSystem.get_default();
let app = appSystem.lookup_app('org.gnome.Nautilus.desktop');
app.activate_full(-1, event.get_time());
});
this._updateMenuVisibility();
}
this._updateMenuVisibility();
},
_updateMenuVisibility() {
if (this._mounts.filter(i => i.visible).length > 0)
this.show();
else
this.hide();
}
_updateMenuVisibility: function() {
if (this._mounts.filter(function(i) i.actor.visible).length > 0)
this.actor.show();
else
this.actor.hide();
},
_addMount(mount) {
let item = new MountMenuItem(mount);
this._mounts.unshift(item);
this.menu.addMenuItem(item, 0);
_addMount: function(mount) {
let item = new MountMenuItem(mount);
this._mounts.unshift(item);
this.menu.addMenuItem(item, 0);
},
item.connect('notify::visible', () => this._updateMenuVisibility());
}
_removeMount: function(mount) {
for (let i = 0; i < this._mounts.length; i++) {
let item = this._mounts[i];
if (item.mount == mount) {
item.destroy();
this._mounts.splice(i, 1);
return;
}
}
log ('Removing a mount that was never added to the menu');
},
_removeMount(mount) {
for (let i = 0; i < this._mounts.length; i++) {
let item = this._mounts[i];
if (item.mount === mount) {
item.destroy();
this._mounts.splice(i, 1);
return;
}
}
log('Removing a mount that was never added to the menu');
}
destroy: function() {
if (this._connectedId) {
this._monitor.disconnect(this._connectedId);
this._monitor.disconnect(this._disconnectedId);
this._connectedId = 0;
this._disconnectedId = 0;
_onDestroy() {
if (this._addedId) {
this._monitor.disconnect(this._addedId);
this._monitor.disconnect(this._removedId);
this._addedId = 0;
this._removedId = 0;
}
this.parent();
},
super._onDestroy();
}
});
/** */
function init() {
Convenience.initTranslations();
ExtensionUtils.initTranslations();
}
let _indicator;
/** */
function enable() {
_indicator = new DriveMenu;
_indicator = new DriveMenu();
Main.panel.addToStatusArea('drive-menu', _indicator);
}
/** */
function disable() {
_indicator.destroy();
}

View File

@@ -0,0 +1,5 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)

View File

@@ -1 +1,7 @@
/* This extensions requires no custom styling */
.drive-menu-item { spacing: 12px; }
.drive-menu-item .button {
border-radius: 99px;
padding: 3px;
min-height: auto;
}

View File

@@ -1,6 +0,0 @@
EXTENSION_ID = example
EXTRA_MODULES = prefs.js
include ../../extension.mk
include ../../settings.mk

View File

@@ -1,49 +0,0 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Sample extension code, makes clicking on the panel show a message
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
function _showHello() {
let settings = Convenience.getSettings();
let text = settings.get_string('hello-text') || _("Hello, world!");
let label = new St.Label({ style_class: 'helloworld-label', text: text });
let monitor = Main.layoutManager.primaryMonitor;
global.stage.add_actor(label);
label.set_position(Math.floor (monitor.width / 2 - label.width / 2), Math.floor(monitor.height / 2 - label.height / 2));
Mainloop.timeout_add(3000, function () { label.destroy(); });
}
// Put your extension initialization code here
function init(metadata) {
log ('Example extension initalized');
Convenience.initTranslations();
}
let signalId;
function enable() {
log ('Example extension enabled');
Main.panel.actor.reactive = true;
signalId = Main.panel.actor.connect('button-release-event', _showHello);
}
function disable() {
log ('Example extension disabled');
if (signalId) {
Main.panel.actor.disconnect(signalId);
signalId = 0;
}
}

View File

@@ -1,10 +0,0 @@
{
"extension-id": "@extension_id@",
"uuid": "@uuid@",
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Hello, World!",
"description": "An example extension to show how it works. Shows Hello, world when clicking on the top panel.",
"shell-version": [ "@shell_current@" ],
"url": "@url@"
}

View File

@@ -1,9 +0,0 @@
<schemalist gettext-domain="gnome-shell-extensions">
<schema id="org.gnome.shell.extensions.example" path="/org/gnome/shell/extensions/example/">
<key name="hello-text" type="s">
<default>''</default>
<summary>Alternative greeting text.</summary>
<description>If not empty, it contains the text that will be shown when clicking on the panel.</description>
</key>
</schema>
</schemalist>

View File

@@ -1,57 +0,0 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
function init() {
Convenience.initTranslations();
}
const ExamplePrefsWidget = new GObject.Class({
Name: 'Example.Prefs.Widget',
GTypeName: 'ExamplePrefsWidget',
Extends: Gtk.Grid,
_init: function(params) {
this.parent(params);
this.margin = 12;
this.row_spacing = this.column_spacing = 6;
this.set_orientation(Gtk.Orientation.VERTICAL);
this.add(new Gtk.Label({ label: '<b>' + _("Message") + '</b>',
use_markup: true,
halign: Gtk.Align.START }));
let entry = new Gtk.Entry({ hexpand: true,
margin_bottom: 12 });
this.add(entry);
this._settings = Convenience.getSettings();
this._settings.bind('hello-text', entry, 'text', Gio.SettingsBindFlags.DEFAULT);
// TRANSLATORS: Example is the name of the extension, should not be
// translated
let primaryText = _("Example aims to show how to build well behaved \
extensions for the Shell and as such it has little functionality on its own.\n\
Nevertheless its possible to customize the greeting message.");
this.add(new Gtk.Label({ label: primaryText,
wrap: true, xalign: 0 }));
}
});
function buildPrefsWidget() {
let widget = new ExamplePrefsWidget();
widget.show_all();
return widget;
}

View File

@@ -1,8 +0,0 @@
/* Example stylesheet */
.helloworld-label {
font-size: 36px;
font-weight: bold;
color: #ffffff;
background-color: rgba(10,10,10,0.7);
border-radius: 5px;
}

View File

@@ -1,3 +0,0 @@
EXTENSION_ID = launch-new-instance
include ../../extension.mk

View File

@@ -1,17 +1,17 @@
/* exported enable disable */
const AppDisplay = imports.ui.appDisplay;
let _activateOriginal = null;
function init() {
}
/** */
function enable() {
_activateOriginal = AppDisplay.AppIcon.prototype.activate;
AppDisplay.AppIcon.prototype.activate = function() {
_activateOriginal.call(this, 2);
};
_activateOriginal = AppDisplay.AppIcon.prototype.activate;
AppDisplay.AppIcon.prototype.activate = function () {
_activateOriginal.call(this, 2);
};
}
/** */
function disable() {
AppDisplay.AppIcon.prototype.activate = _activateOriginal;
AppDisplay.AppIcon.prototype.activate = _activateOriginal;
}

View File

@@ -0,0 +1,5 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)

View File

@@ -4,7 +4,7 @@
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"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 Bugzilla instead.",
"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@"
}

29
extensions/meson.build Normal file
View File

@@ -0,0 +1,29 @@
extension_schemas = []
js_sources = []
metadata_name = 'metadata.json'
foreach e : enabled_extensions
uuid = e + uuid_suffix
metadata_conf = configuration_data()
metadata_conf.set('extension_id', e)
metadata_conf.set('uuid', uuid)
metadata_conf.set('gschemaname', 'org.gnome.shell.extensions.' + e)
metadata_conf.set('gettext_domain', gettext_domain)
metadata_conf.set('shell_current', shell_version)
metadata_conf.set('url', 'https://gitlab.gnome.org/GNOME/gnome-shell-extensions')
extension_sources = files(e + '/extension.js')
extension_data = files(e + '/stylesheet.css')
subdir(e)
install_data (extension_sources + extension_data,
install_dir: join_paths(extensiondir, uuid)
)
endforeach
install_data (extension_schemas,
install_dir: schemadir
)

View File

@@ -0,0 +1,8 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
# extension_sources += files('prefs.js')
# extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -1,5 +0,0 @@
EXTENSION_ID = native-window-placement
include ../../extension.mk
include ../../settings.mk

View File

@@ -1,149 +1,96 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// import just everything from workspace.js:
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Signals = imports.signals;
const DND = imports.ui.dnd;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
const WindowPositionFlags = Workspace.WindowPositionFlags;
/* exported enable disable */
const { Clutter } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const Main = imports.ui.main;
const { WindowPreview } = imports.ui.windowPreview;
const Workspace = imports.ui.workspace;
// testing settings for natural window placement strategy:
const WINDOW_PLACEMENT_NATURAL_FILLGAPS = true; // enlarge windows at the end to fill gaps // not implemented yet
const WINDOW_PLACEMENT_NATURAL_GRID_FALLBACK = true; // fallback to grid mode if all windows have the same size and positions. // not implemented yet
const WINDOW_PLACEMENT_NATURAL_ACCURACY = 20; // accuracy of window translate moves (KDE-default: 20)
const WINDOW_PLACEMENT_NATURAL_GAPS = 5; // half of the minimum gap between windows
const WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS = 5000; // safety limit for preventing endless loop if something is wrong in the algorithm
const PLACE_WINDOW_CAPTIONS_ON_TOP = true; // place window titles in overview on top of windows with overlap parameter
const WORKSPACE_BORDER_GAP = 10; // minimum gap between the workspace area and the workspace selector
const WINDOW_AREA_TOP_GAP = 20; // minimum gap between the workspace area and the top border. This keeps window captions and close buttons visible. 13px (26/2) should currently be enough.
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.desktop.wm.preferences';
const BUTTON_LAYOUT_KEY = 'button-layout';
function injectToFunction(parent, name, func) {
let origin = parent[name];
parent[name] = function() {
let ret;
ret = origin.apply(this, arguments);
if (ret === undefined)
ret = func.apply(this, arguments);
return ret;
}
}
const Rect = new Lang.Class({
Name: 'NativeWindowPlacement.Rect',
_init: function(x, y, width, height) {
class Rect {
constructor(x, y, width, height) {
[this.x, this.y, this.width, this.height] = [x, y, width, height];
},
}
/**
* used in _calculateWindowTransformationsNatural to replace Meta.Rectangle that is too slow.
*/
copy: function() {
// used in _calculateWindowTransformationsNatural to replace Meta.Rectangle that is too slow.
copy() {
return new Rect(this.x, this.y, this.width, this.height);
},
}
union: function(rect2) {
union(rect2) {
let dest = this.copy();
if (rect2.x < dest.x)
{
if (rect2.x < dest.x) {
dest.width += dest.x - rect2.x;
dest.x = rect2.x;
}
if (rect2.y < dest.y)
{
}
if (rect2.y < dest.y) {
dest.height += dest.y - rect2.y;
dest.y = rect2.y;
}
}
if (rect2.x + rect2.width > dest.x + dest.width)
dest.width = rect2.x + rect2.width - dest.x;
dest.width = rect2.x + rect2.width - dest.x;
if (rect2.y + rect2.height > dest.y + dest.height)
dest.height = rect2.y + rect2.height - dest.y;
dest.height = rect2.y + rect2.height - dest.y;
return dest;
},
}
adjusted: function(dx, dy, dx2, dy2) {
adjusted(dx, dy, dx2, dy2) {
let dest = this.copy();
dest.x += dx;
dest.y += dy;
dest.width += -dx + dx2;
dest.height += -dy + dy2;
return dest;
},
}
overlap: function(rect2) {
return !((this.x + this.width <= rect2.x) ||
(rect2.x + rect2.width <= this.x) ||
(this.y + this.height <= rect2.y) ||
(rect2.y + rect2.height <= this.y));
},
overlap(rect2) {
return !(this.x + this.width <= rect2.x ||
rect2.x + rect2.width <= this.x ||
this.y + this.height <= rect2.y ||
rect2.y + rect2.height <= this.y);
}
center: function() {
center() {
return [this.x + this.width / 2, this.y + this.height / 2];
},
}
translate: function(dx, dy) {
translate(dx, dy) {
this.x += dx;
this.y += dy;
}
});
let winInjections, workspaceInjections, connectedSignals;
function resetState() {
winInjections = { };
workspaceInjections = { };
connectedSignals = [ ];
}
function enable() {
resetState();
class NaturalLayoutStrategy extends Workspace.LayoutStrategy {
constructor(params, settings) {
super(params);
this._settings = settings;
}
let settings = Convenience.getSettings();
let useMoreScreen = settings.get_boolean('use-more-screen');
let windowCaptionsOnTop = settings.get_boolean('window-captions-on-top');
let signalId = settings.connect('changed::use-more-screen', function() {
useMoreScreen = settings.get_boolean('use-more-screen');
});
connectedSignals.push({ obj: settings, id: signalId });
computeLayout(windows, _params) {
return {
windows,
};
}
/**
* _calculateWindowTransformationsNatural:
* @clones: Array of #MetaWindow
*
/*
* Returns clones with matching target coordinates and scales to arrange windows in a natural way that no overlap exists and relative window size is preserved.
* This function is almost a 1:1 copy of the function
* PresentWindowsEffect::calculateWindowTransformationsNatural() from KDE, see:
* https://projects.kde.org/projects/kde/kdebase/kde-workspace/repository/revisions/master/entry/kwin/effects/presentwindows/presentwindows.cpp
*/
Workspace.Workspace.prototype._calculateWindowTransformationsNatural = function(clones, area) {
computeWindowSlots(layout, area) {
// 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.
let area_rect = new Rect(area.x, area.y, area.width, area.height);
let bounds = area_rect.copy();
let areaRect = new Rect(area.x, area.y, area.width, area.height);
let bounds = areaRect.copy();
let clones = layout.windows;
let direction = 0;
let directions = [];
@@ -157,36 +104,36 @@ function enable() {
// This is used when the window is on the edge of the screen to try to use as much screen real estate as possible.
directions[i] = direction;
direction++;
if (direction == 4) {
if (direction === 4)
direction = 0;
}
}
let loop_counter = 0;
let loopCounter = 0;
let overlap;
do {
overlap = false;
for (let i = 0; i < rects.length; i++) {
for (let j = 0; j < rects.length; j++) {
if (i != j && rects[i].adjusted(-WINDOW_PLACEMENT_NATURAL_GAPS, -WINDOW_PLACEMENT_NATURAL_GAPS,
WINDOW_PLACEMENT_NATURAL_GAPS, WINDOW_PLACEMENT_NATURAL_GAPS).overlap(
rects[j].adjusted(-WINDOW_PLACEMENT_NATURAL_GAPS, -WINDOW_PLACEMENT_NATURAL_GAPS,
WINDOW_PLACEMENT_NATURAL_GAPS, WINDOW_PLACEMENT_NATURAL_GAPS))) {
loop_counter++;
let adjustments = [-1, -1, 1, 1]
.map(v => (v *= WINDOW_PLACEMENT_NATURAL_GAPS));
let iAdjusted = rects[i].adjusted(...adjustments);
let jAdjusted = rects[j].adjusted(...adjustments);
if (i !== j && iAdjusted.overlap(jAdjusted)) {
loopCounter++;
overlap = true;
// TODO: something like a Point2D would be nicer here:
// Determine pushing direction
let i_center = rects[i].center();
let j_center = rects[j].center();
let diff = [j_center[0] - i_center[0], j_center[1] - i_center[1]];
let iCenter = rects[i].center();
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)
if (diff[0] === 0 && diff[1] === 0)
diff[0] = 1;
// Try to keep screen/workspace aspect ratio
if ( bounds.height / bounds.width > area_rect.height / area_rect.width )
if (bounds.height / bounds.width > areaRect.height / areaRect.width)
diff[0] *= 2;
else
diff[1] *= 2;
@@ -201,7 +148,7 @@ function enable() {
rects[j].translate(diff[0], diff[1]);
if (useMoreScreen) {
if (this._settings.get_boolean('use-more-screen')) {
// Try to keep the bounding rect the same aspect as the screen so that more
// screen real estate is utilised. We do this by splitting the screen into nine
// equal sections, if the window center is in any of the corner sections pull the
@@ -215,33 +162,33 @@ function enable() {
let xSection = Math.round((rects[i].x - bounds.x) / (bounds.width / 3));
let ySection = Math.round((rects[i].y - bounds.y) / (bounds.height / 3));
let i_center = rects[i].center();
iCenter = rects[i].center();
diff[0] = 0;
diff[1] = 0;
if (xSection != 1 || ySection != 1) { // Remove this if you want the center to pull as well
if (xSection == 1)
xSection = (directions[i] / 2 ? 2 : 0);
if (ySection == 1)
ySection = (directions[i] % 2 ? 2 : 0);
if (xSection !== 1 || ySection !== 1) { // Remove this if you want the center to pull as well
if (xSection === 1)
xSection = directions[i] / 2 ? 2 : 0;
if (ySection === 1)
ySection = directions[i] % 2 ? 2 : 0;
}
if (xSection == 0 && ySection == 0) {
diff[0] = bounds.x - i_center[0];
diff[1] = bounds.y - i_center[1];
if (xSection === 0 && ySection === 0) {
diff[0] = bounds.x - iCenter[0];
diff[1] = bounds.y - iCenter[1];
}
if (xSection == 2 && ySection == 0) {
diff[0] = bounds.x + bounds.width - i_center[0];
diff[1] = bounds.y - i_center[1];
if (xSection === 2 && ySection === 0) {
diff[0] = bounds.x + bounds.width - iCenter[0];
diff[1] = bounds.y - iCenter[1];
}
if (xSection == 2 && ySection == 2) {
diff[0] = bounds.x + bounds.width - i_center[0];
diff[1] = bounds.y + bounds.height - i_center[1];
if (xSection === 2 && ySection === 2) {
diff[0] = bounds.x + bounds.width - iCenter[0];
diff[1] = bounds.y + bounds.height - iCenter[1];
}
if (xSection == 0 && ySection == 2) {
diff[0] = bounds.x - i_center[0];
diff[1] = bounds.y + bounds.height - i_center[1];
if (xSection === 0 && ySection === 2) {
diff[0] = bounds.x - iCenter[0];
diff[1] = bounds.y + bounds.height - iCenter[1];
}
if (diff[0] != 0 || diff[1] != 0) {
let length = Math.sqrt(diff[0]*diff[0] + diff[1]*diff[1]);
if (diff[0] !== 0 || diff[1] !== 0) {
length = Math.sqrt(diff[0] * diff[0] + diff[1] * diff[1]);
diff[0] *= WINDOW_PLACEMENT_NATURAL_ACCURACY / length / 2; // /2 to make it less influencing than the normal center-move above
diff[1] *= WINDOW_PLACEMENT_NATURAL_ACCURACY / length / 2;
rects[i].translate(diff[0], diff[1]);
@@ -254,196 +201,94 @@ function enable() {
}
}
}
} while (overlap && loop_counter < WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS);
} while (overlap && loopCounter < WINDOW_PLACEMENT_NATURAL_MAX_TRANSLATIONS);
// Work out scaling by getting the most top-left and most bottom-right window coords.
let scale;
scale = Math.min(area_rect.width / bounds.width,
area_rect.height / bounds.height,
1.0);
scale = Math.min(
areaRect.width / bounds.width,
areaRect.height / bounds.height,
1.0);
// Make bounding rect fill the screen size for later steps
bounds.x = bounds.x - (area_rect.width - bounds.width * scale) / 2;
bounds.y = bounds.y - (area_rect.height - bounds.height * scale) / 2;
bounds.width = area_rect.width / scale;
bounds.height = area_rect.height / scale;
bounds.x -= (areaRect.width - bounds.width * scale) / 2;
bounds.y -= (areaRect.height - bounds.height * scale) / 2;
bounds.width = areaRect.width / scale;
bounds.height = areaRect.height / scale;
// Move all windows back onto the screen and set their scale
for (let i = 0; i < rects.length; i++) {
for (let i = 0; i < rects.length; i++)
rects[i].translate(-bounds.x, -bounds.y);
}
// TODO: Implement the KDE part "Try to fill the gaps by enlarging windows if they have the space" here. (If this is wanted)
// rescale to workspace
let scales = [];
let buttonOuterHeight, captionHeight;
let buttonOuterWidth = 0;
let slots = [];
for (let i = 0; i < rects.length; i++) {
rects[i].x = rects[i].x * scale + area_rect.x;
rects[i].y = rects[i].y * scale + area_rect.y;
rects[i].x = rects[i].x * scale + areaRect.x;
rects[i].y = rects[i].y * scale + areaRect.y;
rects[i].width *= scale;
rects[i].height *= scale;
slots.push([rects[i].x, rects[i].y, scale, clones[i]]);
slots.push([rects[i].x, rects[i].y, rects[i].width, rects[i].height, clones[i]]);
}
return slots;
}
workspaceInjections['_calculateWindowTransformationsNatural'] = undefined;
/**
* _updateWindowPositions:
* @flags:
* INITIAL - this is the initial positioning of the windows.
* ANIMATE - Indicates that we need animate changing position.
*/
workspaceInjections['_updateWindowPositions'] = Workspace.Workspace.prototype._updateWindowPositions;
Workspace.Workspace.prototype._updateWindowPositions = function(flags) {
if (this._currentLayout == null) {
this._recalculateWindowPositions(flags);
return;
}
let initialPositioning = flags & WindowPositionFlags.INITIAL;
let animate = flags & WindowPositionFlags.ANIMATE;
let layout = this._currentLayout;
let strategy = layout.strategy;
let [, , padding] = this._getSpacingAndPadding();
let area = Workspace.padArea(this._actualGeometry, padding);
/// EDIT replace this version by our own:
//let slots = strategy.computeWindowSlots(layout, area);
/// EDIT copied from _realRecalculateWindowPositions:
let clones = this._windows.slice();
if (clones.length == 0)
return;
clones.sort(function(a, b) {
return a.metaWindow.get_stable_sequence() - b.metaWindow.get_stable_sequence();
});
if (this._reservedSlot)
clones.push(this._reservedSlot);
/// EDIT our own window placement function:
let slots = this._calculateWindowTransformationsNatural(clones, area);
let currentWorkspace = global.screen.get_active_workspace();
let isOnCurrentWorkspace = this.metaWorkspace == null || this.metaWorkspace == currentWorkspace;
for (let i = 0; i < slots.length; i++) {
let slot = slots[i];
let [x, y, scale, clone] = slot;
let metaWindow = clone.metaWindow;
let overlay = clone.overlay;
clone.slotId = i;
// Positioning a window currently being dragged must be avoided;
// we'll just leave a blank spot in the layout for it.
if (clone.inDrag)
continue;
let cloneWidth = clone.actor.width * scale;
let cloneHeight = clone.actor.height * scale;
clone.slot = [x, y, cloneWidth, cloneHeight];
if (overlay && (initialPositioning || !clone.positioned))
overlay.hide();
if (!clone.positioned) {
// This window appeared after the overview was already up
// Grow the clone from the center of the slot
clone.actor.x = x + cloneWidth / 2;
clone.actor.y = y + cloneHeight / 2;
clone.actor.scale_x = 0;
clone.actor.scale_y = 0;
clone.positioned = true;
}
if (animate && isOnCurrentWorkspace) {
if (!metaWindow.showing_on_its_workspace()) {
/* Hidden windows should fade in and grow
* therefore we need to resize them now so they
* can be scaled up later */
if (initialPositioning) {
clone.actor.opacity = 0;
clone.actor.scale_x = 0;
clone.actor.scale_y = 0;
clone.actor.x = x;
clone.actor.y = y;
}
Tweener.addTween(clone.actor,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
transition: 'easeInQuad'
});
}
this._animateClone(clone, overlay, x, y, scale, initialPositioning);
} else {
// cancel any active tweens (otherwise they might override our changes)
Tweener.removeTweens(clone.actor);
clone.actor.set_position(x, y);
clone.actor.set_scale(scale, scale);
clone.overlay.relayout(false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
}
}
}
/// position window titles on top of windows in overlay ////
if (windowCaptionsOnTop) {
/// This is almost a direct copy of the original relayout function. Differences are marked.
winInjections['relayout'] = Workspace.WindowOverlay.prototype.relayout;
Workspace.WindowOverlay.prototype.relayout = function(animate) {
winInjections['relayout'].call(this, animate);
let title = this.title;
let border = this.border;
this._parentActor.set_child_above_sibling(title, border);
Tweener.removeTweens(title);
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
// Clutter.Actor.get_preferred_width() will return the fixed width if one
// is set, so we need to reset the width by calling set_width(-1), to forward
// the call down to StLabel.
// We also need to save and restore the current width, otherwise the animation
// starts from the wrong point.
let prevTitleWidth = title.width;
title.set_width(-1);
let [titleMinWidth, titleNatWidth] = title.get_preferred_width(-1);
let titleWidth = Math.max(titleMinWidth, Math.min(titleNatWidth, cloneWidth));
title.width = prevTitleWidth;
let titleX = cloneX + (cloneWidth - titleWidth) / 2;
/// this is the actual difference to original gnome-shell:
//let titleY = cloneY + cloneHeight + title._spacing;
let titleY = cloneY - title.height + title._spacing;
if (animate)
this._animateOverlayActor(title, Math.floor(titleX), Math.floor(titleY), titleWidth);
else {
title.width = titleWidth;
title.set_position(Math.floor(titleX), Math.floor(titleY));
}
};
}
}
let winInjections, workspaceInjections;
/** */
function resetState() {
winInjections = { };
workspaceInjections = { };
}
/** */
function enable() {
resetState();
let settings = ExtensionUtils.getSettings();
workspaceInjections['_createBestLayout'] = Workspace.WorkspaceLayout.prototype._createBestLayout;
Workspace.WorkspaceLayout.prototype._createBestLayout = function (_area) {
this._layoutStrategy = new NaturalLayoutStrategy({
monitor: Main.layoutManager.monitors[this._monitorIndex],
}, settings);
return this._layoutStrategy.computeLayout(this._sortedWindows);
};
// position window titles on top of windows in overlay
winInjections['_init'] = WindowPreview.prototype._init;
WindowPreview.prototype._init = function (...args) {
winInjections['_init'].call(this, ...args);
if (!settings.get_boolean('window-captions-on-top'))
return;
const alignConstraint = this._title.get_constraints().find(
c => c.align_axis && c.align_axis === Clutter.AlignAxis.Y_AXIS);
alignConstraint.factor = 0;
const bindConstraint = this._title.get_constraints().find(
c => c.coordinate && c.coordinate === Clutter.BindCoordinate.Y);
bindConstraint.offset = 0;
};
winInjections['_adjustOverlayOffsets'] =
WindowPreview.prototype._adjustOverlayOffsets;
WindowPreview.prototype._adjustOverlayOffsets = function (...args) {
winInjections['_adjustOverlayOffsets'].call(this, ...args);
if (settings.get_boolean('window-captions-on-top'))
this._title.translation_y = -this._title.translation_y;
};
}
/**
* @param {Object} object - object that was modified
* @param {Object} injection - the map of previous injections
* @param {string} name - the @injection key that should be removed
*/
function removeInjection(object, injection, name) {
if (injection[name] === undefined)
delete object[name];
@@ -451,21 +296,15 @@ function removeInjection(object, injection, name) {
object[name] = injection[name];
}
/** */
function disable() {
var i;
for (i in workspaceInjections)
removeInjection(Workspace.Workspace.prototype, workspaceInjections, i);
removeInjection(Workspace.WorkspaceLayout.prototype, workspaceInjections, i);
for (i in winInjections)
removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
for each (i in connectedSignals)
i.obj.disconnect(i.id);
removeInjection(WindowPreview.prototype, winInjections, i);
global.stage.queue_relayout();
resetState();
}
function init() {
/* do nothing */
}

View File

@@ -0,0 +1,7 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -1,9 +1 @@
.window-caption {
-shell-caption-spacing: 13px; /* current caption height is 26px => set it to half of it. TODO: better solution needed */
}
.window-picker {
-horizontal-spacing: 32px;
-vertical-spacing: 32px;
padding: 64px 32px;
}
/* This extensions requires no special styling */

View File

@@ -1,5 +0,0 @@
EXTENSION_ID = places-menu
EXTRA_MODULES = placeDisplay.js
include ../../extension.mk

View File

@@ -1,143 +1,155 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported init enable disable */
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const { Clutter, GObject, St } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Panel = imports.ui.panel;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = function(x) { return x; }
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const PlaceDisplay = Me.imports.placeDisplay;
const _ = ExtensionUtils.gettext;
const N_ = x => x;
const PLACE_ICON_SIZE = 16;
const PlaceMenuItem = new Lang.Class({
Name: 'PlaceMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
var PlaceMenuItem = GObject.registerClass(
class PlaceMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(info) {
super._init({
style_class: 'place-menu-item',
});
this._info = info;
_init: function(info) {
this.parent();
this._info = info;
this._icon = new St.Icon({
gicon: info.icon,
icon_size: PLACE_ICON_SIZE,
});
this.add_child(this._icon);
this._icon = new St.Icon({ gicon: info.icon,
icon_size: PLACE_ICON_SIZE });
this.actor.add_child(this._icon);
this._label = new St.Label({
text: info.name,
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
this.add_child(this._label);
this._label = new St.Label({ text: info.name });
this.actor.add_child(this._label);
if (info.isRemovable()) {
this._ejectIcon = new St.Icon({
icon_name: 'media-eject-symbolic',
style_class: 'popup-menu-icon',
});
this._ejectButton = new St.Button({
child: this._ejectIcon,
style_class: 'button',
});
this._ejectButton.connect('clicked', info.eject.bind(info));
this.add_child(this._ejectButton);
}
this._changedId = info.connect('changed',
Lang.bind(this, this._propertiesChanged));
},
this._propertiesChanged.bind(this));
}
destroy: function() {
destroy() {
if (this._changedId) {
this._info.disconnect(this._changedId);
this._changedId = 0;
}
this.parent();
},
super.destroy();
}
activate: function(event) {
this._info.launch(event.get_time());
activate(event) {
this._info.launch(event.get_time());
this.parent(event);
},
super.activate(event);
}
_propertiesChanged: function(info) {
_propertiesChanged(info) {
this._icon.gicon = info.icon;
this._label.text = info.name;
},
}
});
const SECTIONS = [
'special',
'devices',
'bookmarks',
'network'
]
'network',
];
const PlacesMenu = new Lang.Class({
Name: 'PlacesMenu.PlacesMenu',
Extends: PanelMenu.Button,
let PlacesMenu = GObject.registerClass(
class PlacesMenu extends PanelMenu.Button {
_init() {
super._init(0.0, _('Places'));
_init: function() {
this.parent(0.0, _("Places"));
let hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
let label = new St.Label({ text: _("Places"),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
hbox.add_child(label);
hbox.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.actor.add_actor(hbox);
let label = new St.Label({
text: _('Places'),
y_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
this.add_actor(label);
this.placesManager = new PlaceDisplay.PlacesManager();
this._sections = { };
this._sections = { };
for (let i=0; i < SECTIONS.length; i++) {
let id = SECTIONS[i];
this._sections[id] = new PopupMenu.PopupMenuSection();
this.placesManager.connect(id + '-updated', Lang.bind(this, function() {
this._redisplay(id);
}));
for (let i = 0; i < SECTIONS.length; i++) {
let id = SECTIONS[i];
this._sections[id] = new PopupMenu.PopupMenuSection();
this.placesManager.connect(`${id}-updated`, () => {
this._redisplay(id);
});
this._create(id);
this.menu.addMenuItem(this._sections[id]);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
}
},
this._create(id);
this.menu.addMenuItem(this._sections[id]);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
}
}
destroy: function() {
this.placesManager.destroy();
_onDestroy() {
this.placesManager.destroy();
this.parent();
},
super._onDestroy();
}
_redisplay: function(id) {
this._sections[id].removeAll();
_redisplay(id) {
this._sections[id].removeAll();
this._create(id);
},
}
_create: function(id) {
_create(id) {
let places = this.placesManager.get(id);
for (let i = 0; i < places.length; i++)
this._sections[id].addMenuItem(new PlaceMenuItem(places[i]));
this._sections[id].actor.visible = places.length > 0;
this._sections[id].actor.visible = places.length > 0;
}
});
/** */
function init() {
Convenience.initTranslations();
ExtensionUtils.initTranslations();
}
let _indicator;
/** */
function enable() {
_indicator = new PlacesMenu;
_indicator = new PlacesMenu();
let pos = 1;
let pos = Main.sessionMode.panel.left.indexOf('appMenu');
if ('apps-menu' in Main.panel.statusArea)
pos = 2;
pos++;
Main.panel.addToStatusArea('places-menu', _indicator, pos, 'left');
}
/** */
function disable() {
_indicator.destroy();
}

View File

@@ -0,0 +1,7 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('placeDisplay.js')

View File

@@ -4,7 +4,7 @@
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Places Status Indicator",
"description": "Add a menu for quickly navigating places in the system.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME Bugzilla instead.",
"description": "Add a menu for quickly navigating places in the system.\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

@@ -1,23 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const { Gio, GLib, Shell } = imports.gi;
const Signals = imports.signals;
const St = imports.gi.St;
const DND = imports.ui.dnd;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Search = imports.ui.search;
const ShellMountOperation = imports.ui.shellMountOperation;
const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = function(x) { return x; }
const _ = ExtensionUtils.gettext;
const N_ = x => x;
const BACKGROUND_SCHEMA = 'org.gnome.desktop.background';
@@ -28,78 +19,73 @@ const Hostname1Iface = '<node> \
</node>';
const Hostname1 = Gio.DBusProxy.makeProxyWrapper(Hostname1Iface);
const PlaceInfo = new Lang.Class({
Name: 'PlaceInfo',
class PlaceInfo {
constructor(...params) {
this._init(...params);
}
_init: function(kind, file, name, icon) {
_init(kind, file, name, icon) {
this.kind = kind;
this.file = file;
this.name = name || this._getFileName();
this.icon = icon ? new Gio.ThemedIcon({ name: icon }) : this.getIcon();
},
}
destroy: function() {
},
destroy() {
}
isRemovable: function() {
isRemovable() {
return false;
},
}
_createLaunchCallback: function(launchContext, tryMount) {
return (_ignored, result) => {
async _ensureMountAndLaunch(context, tryMount) {
try {
await this._launchDefaultForUri(this.file.get_uri(), context, null);
} catch (err) {
if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) {
Main.notifyError(_('Failed to launch “%s”').format(this.name), err.message);
return;
}
let source = {
get_icon: () => this.icon,
};
let op = new ShellMountOperation.ShellMountOperation(source);
try {
Gio.AppInfo.launch_default_for_uri_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_MOUNTED)) {
let source = {
get_icon: () => { return this.icon; }
};
let op = new ShellMountOperation.ShellMountOperation(source);
this.file.mount_enclosing_volume(0, op.mountOp, null, (file, result) => {
try {
op.close();
file.mount_enclosing_volume_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED)) {
// e.g. user canceled the password dialog
return;
} catch(e) {
Main.notifyError(_("Failed to mount volume for “%s”").format(this.name), e.message);
return;
}
await this._mountEnclosingVolume(0, op.mountOp, null);
if (tryMount) {
let callback = this._createLaunchCallback(launchContext, false);
Gio.AppInfo.launch_default_for_uri_async(file.get_uri(),
launchContext,
null,
callback);
}
});
} catch(e) {
Main.notifyError(_("Failed to launch “%s”").format(this.name), e.message);
if (tryMount)
this._ensureMountAndLaunch(context, false);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
Main.notifyError(_('Failed to mount volume for “%s”').format(this.name), e.message);
} finally {
op.close();
}
}
},
}
launch: function(timestamp) {
launch(timestamp) {
let launchContext = global.create_app_launch_context(timestamp, -1);
let callback = this._createLaunchCallback(launchContext, true);
Gio.AppInfo.launch_default_for_uri_async(this.file.get_uri(),
launchContext,
null,
callback);
},
this._ensureMountAndLaunch(launchContext, true);
}
getIcon: function() {
this.file.query_info_async('standard::symbolic-icon', 0, 0, null,
Lang.bind(this, function(file, result) {
try {
let info = file.query_info_finish(result);
this.icon = info.get_symbolic_icon();
this.emit('changed');
} catch(e if e instanceof Gio.IOErrorEnum) {
return;
}
}));
getIcon() {
this.file.query_info_async('standard::symbolic-icon',
Gio.FileQueryInfoFlags.NONE,
0,
null,
(file, result) => {
try {
let info = file.query_info_finish(result);
this.icon = info.get_symbolic_icon();
this.emit('changed');
} catch (e) {
if (e instanceof Gio.IOErrorEnum)
return;
throw e;
}
});
// return a generic icon for this kind for now, until we have the
// icon from the query info above
@@ -116,101 +102,164 @@ const PlaceInfo = new Lang.Class({
else
return new Gio.ThemedIcon({ name: 'folder-symbolic' });
}
},
}
_getFileName: function() {
_getFileName() {
try {
let info = this.file.query_info('standard::display-name', 0, null);
return info.get_display_name();
} catch(e if e instanceof Gio.IOErrorEnum) {
return this.file.get_basename();
} catch (e) {
if (e instanceof Gio.IOErrorEnum)
return this.file.get_basename();
throw e;
}
},
});
}
_launchDefaultForUri(uri, context, cancel) {
return new Promise((resolve, reject) => {
Gio.AppInfo.launch_default_for_uri_async(uri, context, cancel, (o, res) => {
try {
Gio.AppInfo.launch_default_for_uri_finish(res);
resolve();
} catch (e) {
reject(e);
}
});
});
}
_mountEnclosingVolume(flags, mountOp, cancel) {
return new Promise((resolve, reject) => {
this.file.mount_enclosing_volume(flags, mountOp, cancel, (o, res) => {
try {
this.file.mount_enclosing_volume_finish(res);
resolve();
} catch (e) {
reject(e);
}
});
});
}
}
Signals.addSignalMethods(PlaceInfo.prototype);
const RootInfo = new Lang.Class({
Name: 'RootInfo',
Extends: PlaceInfo,
class RootInfo extends PlaceInfo {
_init() {
super._init('devices', Gio.File.new_for_path('/'), _('Computer'));
_init: function() {
this.parent('devices', Gio.File.new_for_path('/'), _("Computer"));
let busName = 'org.freedesktop.hostname1';
let objPath = '/org/freedesktop/hostname1';
new Hostname1(Gio.DBus.system, busName, objPath, (obj, error) => {
if (error)
return;
this._proxy = new Hostname1(Gio.DBus.system,
'org.freedesktop.hostname1',
'/org/freedesktop/hostname1',
Lang.bind(this, function(obj, error) {
if (error)
return;
this._proxy = obj;
this._proxy.connect('g-properties-changed',
this._propertiesChanged.bind(this));
this._propertiesChanged(obj);
});
}
this._proxy.connect('g-properties-changed',
Lang.bind(this, this._propertiesChanged));
this._propertiesChanged(obj);
}));
},
getIcon: function() {
getIcon() {
return new Gio.ThemedIcon({ name: 'drive-harddisk-symbolic' });
},
}
_propertiesChanged: function(proxy) {
_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.name = proxy.PrettyHostname || _('Computer');
this.emit('changed');
}
},
destroy: function() {
this._proxy.run_dispose();
this.parent();
}
});
destroy() {
if (this._proxy) {
this._proxy.run_dispose();
this._proxy = null;
}
super.destroy();
}
}
const PlaceDeviceInfo = new Lang.Class({
Name: 'PlaceDeviceInfo',
Extends: PlaceInfo,
_init: function(kind, mount) {
class PlaceDeviceInfo extends PlaceInfo {
_init(kind, mount) {
this._mount = mount;
this.parent(kind, mount.get_root(), mount.get_name());
},
super._init(kind, mount.get_root(), mount.get_name());
}
getIcon: function() {
getIcon() {
return this._mount.get_symbolic_icon();
}
});
const PlaceVolumeInfo = new Lang.Class({
Name: 'PlaceVolumeInfo',
Extends: PlaceInfo,
isRemovable() {
return this._mount.can_eject() || this._mount.can_unmount();
}
_init: function(kind, volume) {
eject() {
let unmountArgs = [
Gio.MountUnmountFlags.NONE,
new ShellMountOperation.ShellMountOperation(this._mount).mountOp,
null, // Gio.Cancellable
];
if (this._mount.can_eject()) {
this._mount.eject_with_operation(...unmountArgs,
this._ejectFinish.bind(this));
} else {
this._mount.unmount_with_operation(...unmountArgs,
this._unmountFinish.bind(this));
}
}
_ejectFinish(mount, result) {
try {
mount.eject_with_operation_finish(result);
} catch (e) {
this._reportFailure(e);
}
}
_unmountFinish(mount, result) {
try {
mount.unmount_with_operation_finish(result);
} catch (e) {
this._reportFailure(e);
}
}
_reportFailure(exception) {
let msg = _('Ejecting drive “%s” failed:').format(this._mount.get_name());
Main.notifyError(msg, exception.message);
}
}
class PlaceVolumeInfo extends PlaceInfo {
_init(kind, volume) {
this._volume = volume;
this.parent(kind, volume.get_activation_root(), volume.get_name());
},
super._init(kind, volume.get_activation_root(), volume.get_name());
}
launch: function(timestamp) {
launch(timestamp) {
if (this.file) {
this.parent(timestamp);
super.launch(timestamp);
return;
}
this._volume.mount(0, null, null, Lang.bind(this, function(volume, result) {
this._volume.mount(0, null, null, (volume, result) => {
volume.mount_finish(result);
let mount = volume.get_mount();
this.file = mount.get_root();
this.parent(timestamp);
}));
},
super.launch(timestamp);
});
}
getIcon: function() {
getIcon() {
return this._volume.get_symbolic_icon();
}
});
}
const DEFAULT_DIRECTORIES = [
GLib.UserDirectory.DIRECTORY_DOCUMENTS,
@@ -220,10 +269,8 @@ const DEFAULT_DIRECTORIES = [
GLib.UserDirectory.DIRECTORY_VIDEOS,
];
const PlacesManager = new Lang.Class({
Name: 'PlacesManager',
_init: function() {
var PlacesManager = class {
constructor() {
this._places = {
special: [],
devices: [],
@@ -232,9 +279,8 @@ const PlacesManager = new Lang.Class({
};
this._settings = new Gio.Settings({ schema_id: BACKGROUND_SCHEMA });
this._showDesktopIconsChangedId =
this._settings.connect('changed::show-desktop-icons',
Lang.bind(this, this._updateSpecials));
this._showDesktopIconsChangedId = this._settings.connect(
'changed::show-desktop-icons', this._updateSpecials.bind(this));
this._updateSpecials();
/*
@@ -244,41 +290,50 @@ const PlacesManager = new Lang.Class({
this._connectVolumeMonitorSignals();
this._updateMounts();
this._bookmarksFile = this._findBookmarksFile()
this._bookmarksFile = this._findBookmarksFile();
this._bookmarkTimeoutId = 0;
this._monitor = null;
if (this._bookmarksFile) {
this._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
this._monitor.connect('changed', Lang.bind(this, function () {
this._monitor.connect('changed', () => {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
}));
}));
this._bookmarkTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, 100, () => {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
});
});
this._reloadBookmarks();
}
},
}
_connectVolumeMonitorSignals: function() {
const signals = ['volume-added', 'volume-removed', 'volume-changed',
'mount-added', 'mount-removed', 'mount-changed',
'drive-connected', 'drive-disconnected', 'drive-changed'];
_connectVolumeMonitorSignals() {
const signals = [
'volume-added',
'volume-removed',
'volume-changed',
'mount-added',
'mount-removed',
'mount-changed',
'drive-connected',
'drive-disconnected',
'drive-changed',
];
this._volumeMonitorSignals = [];
let func = Lang.bind(this, this._updateMounts);
let func = this._updateMounts.bind(this);
for (let i = 0; i < signals.length; i++) {
let id = this._volumeMonitor.connect(signals[i], func);
this._volumeMonitorSignals.push(id);
}
},
}
destroy: function() {
destroy() {
if (this._settings)
this._settings.disconnect(this._showDesktopIconsChangedId);
this._settings = null;
@@ -289,18 +344,19 @@ const PlacesManager = new Lang.Class({
if (this._monitor)
this._monitor.cancel();
if (this._bookmarkTimeoutId)
Mainloop.source_remove(this._bookmarkTimeoutId);
},
GLib.source_remove(this._bookmarkTimeoutId);
}
_updateSpecials: function() {
this._places.special.forEach(function (p) { p.destroy(); });
_updateSpecials() {
this._places.special.forEach(p => p.destroy());
this._places.special = [];
let homePath = GLib.get_home_dir();
this._places.special.push(new PlaceInfo('special',
Gio.File.new_for_path(homePath),
_("Home")));
this._places.special.push(new PlaceInfo(
'special',
Gio.File.new_for_path(homePath),
_('Home')));
let specials = [];
let dirs = DEFAULT_DIRECTORIES.slice();
@@ -310,55 +366,56 @@ const PlacesManager = new Lang.Class({
for (let i = 0; i < dirs.length; i++) {
let specialPath = GLib.get_user_special_dir(dirs[i]);
if (specialPath == null || specialPath == homePath)
if (!specialPath || specialPath === homePath)
continue;
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;
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue;
throw e;
}
specials.push(info);
}
specials.sort(function(a, b) {
return GLib.utf8_collate(a.name, b.name);
});
specials.sort((a, b) => GLib.utf8_collate(a.name, b.name));
this._places.special = this._places.special.concat(specials);
this.emit('special-updated');
},
}
_updateMounts: function() {
_updateMounts() {
let networkMounts = [];
let networkVolumes = [];
this._places.devices.forEach(function (p) { p.destroy(); });
this._places.devices.forEach(p => p.destroy());
this._places.devices = [];
this._places.network.forEach(function (p) { p.destroy(); });
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'));
this._places.network.push(new PlaceInfo(
'network',
Gio.File.new_for_uri('network:///'),
_('Browse Network'),
'network-workgroup-symbolic'));
/* first go through all connected drives */
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
let volumes = drives[i].get_volumes();
for(let j = 0; j < volumes.length; j++) {
for (let j = 0; j < volumes.length; j++) {
let identifier = volumes[j].get_identifier('class');
if (identifier && identifier.indexOf('network') >= 0) {
if (identifier && identifier.includes('network')) {
networkVolumes.push(volumes[j]);
} else {
let mount = volumes[j].get_mount();
if(mount != null)
if (mount)
this._addMount('devices', mount);
}
}
@@ -366,27 +423,27 @@ const PlacesManager = new Lang.Class({
/* add all volumes that is not associated with a drive */
let volumes = this._volumeMonitor.get_volumes();
for(let i = 0; i < volumes.length; i++) {
if(volumes[i].get_drive() != null)
for (let i = 0; i < volumes.length; i++) {
if (volumes[i].get_drive())
continue;
let identifier = volumes[i].get_identifier('class');
if (identifier && identifier.indexOf('network') >= 0) {
if (identifier && identifier.includes('network')) {
networkVolumes.push(volumes[i]);
} else {
let mount = volumes[i].get_mount();
if(mount != null)
if (mount)
this._addMount('devices', mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
let mounts = this._volumeMonitor.get_mounts();
for(let i = 0; i < mounts.length; i++) {
if(mounts[i].is_shadowed())
for (let i = 0; i < mounts.length; i++) {
if (mounts[i].is_shadowed())
continue;
if(mounts[i].get_volume())
if (mounts[i].get_volume())
continue;
let root = mounts[i].get_default_location();
@@ -406,15 +463,15 @@ const PlacesManager = new Lang.Class({
this._addVolume('network', networkVolumes[i]);
}
for (let i = 0; i < networkMounts.length; i++) {
for (let i = 0; i < networkMounts.length; i++)
this._addMount('network', networkMounts[i]);
}
this.emit('devices-updated');
this.emit('network-updated');
},
}
_findBookmarksFile: function() {
_findBookmarksFile() {
let paths = [
GLib.build_filenamev([GLib.get_user_config_dir(), 'gtk-3.0', 'bookmarks']),
GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']),
@@ -426,10 +483,9 @@ const PlacesManager = new Lang.Class({
}
return null;
},
_reloadBookmarks: function() {
}
_reloadBookmarks() {
this._bookmarks = [];
let content = Shell.get_file_contents_utf8_sync(this._bookmarksFile.get_path());
@@ -439,7 +495,7 @@ const PlacesManager = new Lang.Class({
for (let i = 0; i < lines.length; i++) {
let line = lines[i];
let components = line.split(' ');
let bookmark = components[0];
let [bookmark] = components;
if (!bookmark)
continue;
@@ -449,16 +505,16 @@ const PlacesManager = new Lang.Class({
continue;
let duplicate = false;
for (let i = 0; i < this._places.special.length; i++) {
if (file.equal(this._places.special[i].file)) {
for (let j = 0; j < this._places.special.length; j++) {
if (file.equal(this._places.special[j].file)) {
duplicate = true;
break;
}
}
if (duplicate)
continue;
for (let i = 0; i < bookmarks.length; i++) {
if (file.equal(bookmarks[i].file)) {
for (let j = 0; j < bookmarks.length; j++) {
if (file.equal(bookmarks[j].file)) {
duplicate = true;
break;
}
@@ -476,34 +532,38 @@ const PlacesManager = new Lang.Class({
this._places.bookmarks = bookmarks;
this.emit('bookmarks-updated');
},
}
_addMount: function(kind, mount) {
_addMount(kind, mount) {
let devItem;
try {
devItem = new PlaceDeviceInfo(kind, mount);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
return;
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
return;
throw e;
}
this._places[kind].push(devItem);
},
}
_addVolume: function(kind, volume) {
_addVolume(kind, volume) {
let volItem;
try {
volItem = new PlaceVolumeInfo(kind, volume);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
return;
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
return;
throw e;
}
this._places[kind].push(volItem);
},
}
get: function (kind) {
get(kind) {
return this._places[kind];
}
});
};
Signals.addSignalMethods(PlacesManager.prototype);

View File

@@ -1 +1,8 @@
/* none used*/
.place-menu-item .button {
border-radius: 99px;
padding: 3px;
min-height: auto;
}
.place-menu-item .button:ltr { margin-left: 6px; }
.place-menu-item .button:rtl { margin-right: 6px; }

View File

@@ -1,4 +0,0 @@
EXTENSION_ID = screenshot-window-sizer
include ../../extension.mk
include ../../settings.mk

View File

@@ -1,3 +1,4 @@
/* exported enable disable */
/* Screenshot Window Sizer for Gnome Shell
*
* Copyright (c) 2013 Owen Taylor <otaylor@redhat.com>
@@ -18,47 +19,46 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const { Clutter, Meta, Shell, St } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const Main = imports.ui.main;
const MESSAGE_FADE_TIME = 2;
const MESSAGE_FADE_TIME = 2000;
let text, button;
let text;
/** */
function hideMessage() {
text.destroy();
text = null;
}
/**
* @param {string} message - the message to flash
*/
function flashMessage(message) {
if (!text) {
text = new St.Label({ style_class: 'screenshot-sizer-message' });
Main.uiGroup.add_actor(text);
}
Tweener.removeTweens(text);
text.remove_all_transitions();
text.text = message;
text.opacity = 255;
let monitor = Main.layoutManager.primaryMonitor;
text.set_position(monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
text.set_position(
monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
Tweener.addTween(text,
{ opacity: 0,
time: MESSAGE_FADE_TIME,
transition: 'easeOutQuad',
onComplete: hideMessage });
text.ease({
opacity: 0,
duration: MESSAGE_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: hideMessage,
});
}
let SIZES = [
@@ -66,29 +66,33 @@ let SIZES = [
[800, 450],
[1024, 576],
[1200, 675],
[1600, 900]
[1600, 900],
[360, 654], // Phone portrait maximized
[720, 360], // Phone landscape fullscreen
];
function cycleScreenshotSizes(display, screen, window, binding) {
/**
* @param {Meta.Display} display - the display
* @param {Meta.Window=} window - for per-window bindings, the window
* @param {Meta.KeyBinding} binding - the key binding
*/
function cycleScreenshotSizes(display, window, binding) {
// Probably this isn't useful with 5 sizes, but you can decrease instead
// of increase by holding down shift.
let modifiers = binding.get_modifiers();
let backwards = (modifiers & Meta.VirtualModifier.SHIFT_MASK) != 0;
let backwards = (modifiers & Meta.VirtualModifier.SHIFT_MASK) !== 0;
// Unmaximize first
if (window.maximized_horizontally || window.maximizedVertically)
window.unmaximize(Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL);
if (window.get_maximized() !== 0)
window.unmaximize(Meta.MaximizeFlags.BOTH);
let workArea = window.get_work_area_current_monitor();
let outerRect = window.get_frame_rect();
// Double both axes if on a hidpi display
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let scaledSizes = SIZES.map(function(size) {
return size.map(function(wh) {
return wh * scaleFactor;
});
});
let scaledSizes = 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
let nearestIndex;
@@ -103,7 +107,7 @@ function cycleScreenshotSizes(display, screen, window, binding) {
// get the best initial window size
let error = Math.abs(width - outerRect.width) + Math.abs(height - outerRect.height);
if (nearestIndex == null || error < nearestError) {
if (nearestIndex === undefined || error < nearestError) {
nearestIndex = i;
nearestError = error;
}
@@ -111,10 +115,7 @@ function cycleScreenshotSizes(display, screen, window, binding) {
// get the next size up or down from ideal
let newIndex = (nearestIndex + (backwards ? -1 : 1)) % scaledSizes.length;
let newWidth, newHeight;
[newWidth, newHeight] = scaledSizes[newIndex];
if (newWidth > workArea.width || newHeight > workArea.height)
[newWidth, newHeight] = scaledSizes[0];
let [newWidth, newHeight] = scaledSizes[newIndex];
// Push the window onscreen if it would be resized offscreen
let newX = outerRect.x;
@@ -128,36 +129,36 @@ function cycleScreenshotSizes(display, screen, window, binding) {
let newOuterRect = window.get_frame_rect();
let message = '%d×%d'.format(
(newOuterRect.width / scaleFactor),
(newOuterRect.height / scaleFactor));
newOuterRect.width / scaleFactor,
newOuterRect.height / scaleFactor);
// 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
let actualNumerator = (newOuterRect.width / newOuterRect.height) * 9;
let actualNumerator = 9 * newOuterRect.width / newOuterRect.height;
if (Math.abs(actualNumerator - 16) > 0.01)
message += ' (%.2f:9)'.format(actualNumerator);
flashMessage(message);
}
function init() {
}
/** */
function enable() {
Main.wm.addKeybinding('cycle-screenshot-sizes',
Convenience.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
Main.wm.addKeybinding('cycle-screenshot-sizes-backward',
Convenience.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW |
Meta.KeyBindingFlags.IS_REVERSED,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
Main.wm.addKeybinding(
'cycle-screenshot-sizes',
ExtensionUtils.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
Main.wm.addKeybinding(
'cycle-screenshot-sizes-backward',
ExtensionUtils.getSettings(),
Meta.KeyBindingFlags.PER_WINDOW | Meta.KeyBindingFlags.IS_REVERSED,
Shell.ActionMode.NORMAL,
cycleScreenshotSizes);
}
/** */
function disable() {
Main.wm.removeKeybinding('cycle-screenshot-sizes');
Main.wm.removeKeybinding('cycle-screenshot-sizes-backward');

View File

@@ -0,0 +1,7 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist>
<schemalist gettext-domain="gnome-shell-extensions">
<schema id="org.gnome.shell.extensions.screenshot-window-sizer"
path="/org/gnome/shell/extensions/screenshot-window-sizer/">
<key type="as" name="cycle-screenshot-sizes">

View File

@@ -1,5 +0,0 @@
EXTENSION_ID = user-theme
include ../../extension.mk
include ../../settings.mk

View File

@@ -1,71 +1,61 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// Load shell theme from ~/.themes/name/gnome-shell
// Load shell theme from ~/.local/share/themes/name/gnome-shell
/* exported init */
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const { Gio } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const Me = ExtensionUtils.getCurrentExtension();
const Util = Me.imports.util;
const SETTINGS_KEY = 'name';
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const ThemeManager = new Lang.Class({
Name: 'UserTheme.ThemeManager',
_init: function() {
this._settings = Convenience.getSettings();
},
enable: function() {
this._changedId = this._settings.connect('changed::'+SETTINGS_KEY, Lang.bind(this, this._changeTheme));
class ThemeManager {
enable() {
this._settings = ExtensionUtils.getSettings();
this._settings.connect(`changed::${SETTINGS_KEY}`, this._changeTheme.bind(this));
this._changeTheme();
},
}
disable: function() {
if (this._changedId) {
this._settings.disconnect(this._changedId);
this._changedId = 0;
}
disable() {
this._settings?.run_dispose();
this._settings = null;
Main.setThemeStylesheet(null);
Main.loadTheme();
},
}
_changeTheme: function() {
let _stylesheet = null;
let _themeName = this._settings.get_string(SETTINGS_KEY);
_changeTheme() {
let stylesheet = null;
let themeName = this._settings.get_string(SETTINGS_KEY);
if (_themeName) {
let _userCssStylesheet = GLib.get_home_dir() + '/.themes/' + _themeName + '/gnome-shell/gnome-shell.css';
let file = Gio.file_new_for_path(_userCssStylesheet);
if (file.query_exists(null))
_stylesheet = _userCssStylesheet;
else {
let sysdirs = GLib.get_system_data_dirs();
sysdirs.unshift(GLib.get_user_data_dir());
for (let i = 0; i < sysdirs.length; i++) {
_userCssStylesheet = sysdirs[i] + '/themes/' + _themeName + '/gnome-shell/gnome-shell.css';
let file = Gio.file_new_for_path(_userCssStylesheet);
if (file.query_exists(null)) {
_stylesheet = _userCssStylesheet;
break;
}
}
}
if (themeName) {
const stylesheetPaths = Util.getThemeDirs()
.map(dir => `${dir}/${themeName}/gnome-shell/gnome-shell.css`);
stylesheetPaths.push(...Util.getModeThemeDirs()
.map(dir => `${dir}/${themeName}.css`));
stylesheet = stylesheetPaths.find(path => {
let file = Gio.file_new_for_path(path);
return file.query_exists(null);
});
}
if (_stylesheet)
global.log('loading user theme: ' + _stylesheet);
if (stylesheet)
global.log(`loading user theme: ${stylesheet}`);
else
global.log('loading default theme (Adwaita)');
Main.setThemeStylesheet(_stylesheet);
Main.setThemeStylesheet(stylesheet);
Main.loadTheme();
}
});
}
/**
* @returns {ThemeManager} - the extension state object
*/
function init() {
return new ThemeManager();
}

View File

@@ -0,0 +1,8 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('prefs.js', 'util.js')
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')

View File

@@ -0,0 +1,186 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init buildPrefsWidget */
// we use async/await here to not block the mainloop, not to parallelize
/* eslint-disable no-await-in-loop */
const { Gio, GLib, GObject, Gtk } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Util = Me.imports.util;
Gio._promisify(Gio._LocalFilePrototype,
'enumerate_children_async', 'enumerate_children_finish');
Gio._promisify(Gio._LocalFilePrototype,
'query_info_async', 'query_info_finish');
Gio._promisify(Gio.FileEnumerator.prototype,
'next_files_async', 'next_files_finish');
const UserThemePrefsWidget = GObject.registerClass(
class UserThemePrefsWidget extends Gtk.ScrolledWindow {
_init() {
super._init({
hscrollbar_policy: Gtk.PolicyType.NEVER,
});
const box = new Gtk.Box();
this.set_child(box);
this._list = new Gtk.ListBox({
selection_mode: Gtk.SelectionMode.NONE,
show_separators: true,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
hexpand: true,
margin_start: 60,
margin_end: 60,
margin_top: 60,
margin_bottom: 60,
});
this._list.get_style_context().add_class('frame');
box.append(this._list);
this._actionGroup = new Gio.SimpleActionGroup();
this._list.insert_action_group('theme', this._actionGroup);
this._settings = ExtensionUtils.getSettings();
this._actionGroup.add_action(
this._settings.create_action('name'));
this.connect('destroy', () => this._settings.run_dispose());
this._rows = new Map();
this._addTheme(''); // default
this._collectThemes();
}
async _collectThemes() {
for (const dirName of Util.getThemeDirs()) {
const dir = Gio.File.new_for_path(dirName);
for (const name of await this._enumerateDir(dir)) {
if (this._rows.has(name))
continue;
const file = dir.resolve_relative_path(
`${name}/gnome-shell/gnome-shell.css`);
try {
await file.query_info_async(
Gio.FILE_ATTRIBUTE_STANDARD_NAME,
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT, null);
this._addTheme(name);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
logError(e);
}
}
}
for (const dirName of Util.getModeThemeDirs()) {
const dir = Gio.File.new_for_path(dirName);
for (const filename of await this._enumerateDir(dir)) {
if (!filename.endsWith('.css'))
continue;
const name = filename.slice(0, -4);
if (!this._rows.has(name))
this._addTheme(name);
}
}
}
_addTheme(name) {
const row = new ThemeRow(name, this._settings);
this._rows.set(name, row);
this._list.append(row);
}
async _enumerateDir(dir) {
const fileInfos = [];
let fileEnum;
try {
fileEnum = await dir.enumerate_children_async(
Gio.FILE_ATTRIBUTE_STANDARD_NAME,
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT, null);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
logError(e);
return [];
}
let infos;
do {
infos = await fileEnum.next_files_async(100,
GLib.PRIORITY_DEFAULT, null);
fileInfos.push(...infos);
} while (infos.length > 0);
return fileInfos.map(info => info.get_name());
}
});
const ThemeRow = GObject.registerClass(
class ThemeRow extends Gtk.ListBoxRow {
_init(name, settings) {
this._name = name;
this._settings = settings;
const box = new Gtk.Box({
spacing: 12,
margin_start: 12,
margin_end: 12,
margin_top: 12,
margin_bottom: 12,
});
super._init({
action_name: 'theme.name',
action_target: new GLib.Variant('s', name),
child: box,
});
box.append(new Gtk.Label({
label: name || 'Default',
hexpand: true,
xalign: 0,
max_width_chars: 25,
width_chars: 25,
}));
this._checkmark = new Gtk.Image({
icon_name: 'emblem-ok-symbolic',
pixel_size: 16,
});
box.append(this._checkmark);
const id = this._settings.connect('changed::name',
this._syncCheckmark.bind(this));
this._syncCheckmark();
this.connect('destroy', () => {
this._settings.disconnect(id);
this._settings = null;
});
}
_syncCheckmark() {
const visible = this._name === this._settings.get_string('name');
this._checkmark.opacity = visible ? 1. : 0;
}
});
/** */
function init() {
}
/**
* @returns {Gtk.Widget} - the prefs widget
*/
function buildPrefsWidget() {
return new UserThemePrefsWidget();
}

View File

@@ -0,0 +1,23 @@
/* exported getThemeDirs getModeThemeDirs */
const { GLib } = imports.gi;
const fn = (...args) => GLib.build_filenamev(args);
/**
* @returns {string[]} - an ordered list of theme directories
*/
function getThemeDirs() {
return [
fn(GLib.get_home_dir(), '.themes'),
fn(GLib.get_user_data_dir(), 'themes'),
...GLib.get_system_data_dirs().map(dir => fn(dir, 'themes')),
];
}
/**
* @returns {string[]} - an ordered list of mode theme directories
*/
function getModeThemeDirs() {
return GLib.get_system_data_dirs()
.map(dir => fn(dir, 'gnome-shell', 'theme'));
}

View File

@@ -1,10 +0,0 @@
EXTENSION_ID = window-list
EXTRA_MODULES = prefs.js
if CLASSIC_MODE
EXTRA_MODULES += classic.css
endif
include ../../extension.mk
include ../../settings.mk

View File

@@ -4,36 +4,39 @@
border-top-width: 1px;
border-bottom-width: 0px;
height: 2.25em ;
padding: 2px;
}
.bottom-panel .window-button > StWidget,
.bottom-panel .window-picker-toggle > 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);
}
.bottom-panel .window-button > StWidget {
background-gradient-drection: vertical;
background-color: #fff;
background-gradient-start: #fff;
background-gradient-end: #eee;
color: #000;
-st-natural-width: 18.7em;
max-width: 18.75em;
color: #2e3436;
background-color: #eee;
border-radius: 2px;
padding: 3px 6px 1px;
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
text-shadow: 0 0 transparent;
}
.bottom-panel .window-button:hover > StWidget {
.bottom-panel .window-button:hover > StWidget,
.bottom-panel .window-picker-toggle:hover > StWidget {
background-color: #f9f9f9;
}
.bottom-panel .window-button:active > StWidget,
.bottom-panel .window-button:focus > StWidget {
box-shadow: inset 1px 1px 2px rgba(0,0,0,0.5);
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
.bottom-panel .window-button.focused > StWidget {
background-color: #ddd;
box-shadow: inset 1px 1px 1px rgba(0,0,0,0.5);
.bottom-panel .window-button.focused > StWidget,
.bottom-panel .window-picker-toggle:checked > StWidget {
background-color: #ccc;
box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
}
.bottom-panel .window-button.focused:hover > StWidget {
@@ -42,5 +45,24 @@
.bottom-panel .window-button.minimized > StWidget {
color: #888;
box-shadow: inset -1px -1px 1px rgba(0,0,0,0.5);
box-shadow: none;
}
/* workspace switcher */
.window-list-workspace-indicator .workspace {
border: 2px solid #f6f5f4;
background-color: #ccc;
}
.window-list-workspace-indicator .workspace.active {
border-color: #888;
}
.window-list-window-preview {
background-color: #ededed;
border: 1px solid #ccc;
}
.window-list-window-preview.active {
background-color: #f6f5f4;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('prefs.js', 'windowPicker.js', 'workspaceIndicator.js')
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
if classic_mode_enabled
extension_data += files('classic.css')
endif

View File

@@ -4,7 +4,7 @@
"settings-schema": "@gschemaname@",
"gettext-domain": "@gettext_domain@",
"name": "Window List",
"description": "Display a window list at the bottom of the screen.\nThis extension is part of Classic Mode and is officially supported by GNOME. Please do not report bugs using the form below, use GNOME Bugzilla instead.",
"description": "Display a window list at the bottom of the screen.\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

@@ -15,6 +15,13 @@
window list. Possible values are “never”, “auto” and “always”.
</description>
</key>
<key name="display-all-workspaces" type="b">
<default>false</default>
<summary>Show windows from all workspaces</summary>
<description>
Whether to show windows from all workspaces or only the current one.
</description>
</key>
<key name="show-on-all-monitors" type="b">
<default>false</default>
<summary>Show the window list on all monitors</summary>

View File

@@ -1,87 +1,97 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init buildPrefsWidget */
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const { Gio, GLib, GObject, Gtk } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _ = ExtensionUtils.gettext;
/** */
function init() {
Convenience.initTranslations();
ExtensionUtils.initTranslations();
}
const WindowListPrefsWidget = new GObject.Class({
Name: 'WindowList.Prefs.Widget',
GTypeName: 'WindowListPrefsWidget',
Extends: Gtk.Grid,
const WindowListPrefsWidget = GObject.registerClass(
class WindowListPrefsWidget extends Gtk.Box {
_init() {
super._init({
orientation: Gtk.Orientation.VERTICAL,
spacing: 6,
margin_top: 36,
margin_bottom: 36,
margin_start: 36,
margin_end: 36,
halign: Gtk.Align.CENTER,
});
_init: function(params) {
this.parent(params);
this._actionGroup = new Gio.SimpleActionGroup();
this.insert_action_group('window-list', this._actionGroup);
this.margin = 24;
this.row_spacing = 6;
this.orientation = Gtk.Orientation.VERTICAL;
this._settings = ExtensionUtils.getSettings();
this._actionGroup.add_action(
this._settings.create_action('grouping-mode'));
this._actionGroup.add_action(
this._settings.create_action('show-on-all-monitors'));
this._actionGroup.add_action(
this._settings.create_action('display-all-workspaces'));
let groupingLabel = '<b>' + _("Window Grouping") + '</b>';
this.add(new Gtk.Label({ label: groupingLabel, use_markup: true,
halign: Gtk.Align.START }));
let groupingLabel = '<b>%s</b>'.format(_('Window Grouping'));
this.append(new Gtk.Label({
label: groupingLabel, use_markup: true,
halign: Gtk.Align.START,
}));
let align = new Gtk.Alignment({ left_padding: 12 });
this.add(align);
const box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin_bottom: 12,
});
this.append(box);
let grid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
row_spacing: 6,
column_spacing: 6 });
align.add(grid);
const context = box.get_style_context();
const cssProvider = new Gtk.CssProvider();
cssProvider.load_from_data(
'box { padding: 12px; }');
this._settings = Convenience.getSettings();
let currentMode = this._settings.get_string('grouping-mode');
let range = this._settings.get_range('grouping-mode');
let modes = range.deep_unpack()[1].deep_unpack();
context.add_provider(cssProvider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
context.add_class('frame');
context.add_class('view');
let modeLabels = {
'never': _("Never group windows"),
'auto': _("Group windows when space is limited"),
'always': _("Always group windows")
};
let radio = null;
for (let i = 0; i < modes.length; i++) {
let mode = modes[i];
let label = modeLabels[mode];
if (!label) {
log('Unhandled option "%s" for grouping-mode'.format(mode));
continue;
}
radio = new Gtk.RadioButton({ active: currentMode == mode,
label: label,
group: radio });
grid.add(radio);
radio.connect('toggled', Lang.bind(this, function(button) {
if (button.active)
this._settings.set_string('grouping-mode', mode);
}));
const modes = [
{ mode: 'never', label: _('Never group windows') },
{ mode: 'auto', label: _('Group windows when space is limited') },
{ mode: 'always', label: _('Always group windows') },
];
let group = null;
for (const { mode, label } of modes) {
const check = new Gtk.CheckButton({
action_name: 'window-list.grouping-mode',
action_target: new GLib.Variant('s', mode),
label,
group,
margin_end: 12,
});
group = check;
box.append(check);
}
let check = new Gtk.CheckButton({ label: _("Show on all monitors"),
margin_top: 6 });
this._settings.bind('show-on-all-monitors', check, 'active', Gio.SettingsBindFlags.DEFAULT);
this.add(check);
this.append(new Gtk.CheckButton({
label: _('Show on all monitors'),
action_name: 'window-list.show-on-all-monitors',
}));
this.append(new Gtk.CheckButton({
label: _('Show windows from all workspaces'),
action_name: 'window-list.display-all-workspaces',
}));
}
});
/**
* @returns {Gtk.Widget} - the prefs widget
*/
function buildPrefsWidget() {
let widget = new WindowListPrefsWidget();
widget.show_all();
return widget;
return new WindowListPrefsWidget();
}

View File

@@ -1,10 +1,3 @@
.bottom-panel {
/* .window-button-icon height +
.window-button vertical padding +
.window-button > StWidget vertical padding) */
height: 2.25em;
}
.window-list {
spacing: 2px;
font-size: 10pt;
@@ -26,18 +19,31 @@
spacing: 4px;
}
.window-button > StWidget {
-st-natural-width: 18.75em;
max-width: 18.75em;
.window-button > StWidget,
.window-picker-toggle > StWidget {
color: #bbb;
background-color: black;
border-radius: 4px;
border-radius: 2px;
padding: 3px 6px 1px;
box-shadow: inset 1px 1px 4px rgba(255,255,255,0.5);
text-shadow: 1px 1px 4px rgba(0,0,0,0.8);
}
.window-button:hover > StWidget {
.window-picker-toggle {
padding: 3px;
}
.window-picker-toggle > StWidet {
border: 1px solid rgba(255,255,255,0.3);
}
.window-button > StWidget {
-st-natural-width: 18.75em;
max-width: 18.75em;
}
.window-button:hover > StWidget,
.window-picker-toggle:hover > StWidget {
color: white;
background-color: #1f1f1f;
}
@@ -47,12 +53,14 @@
box-shadow: inset 2px 2px 4px rgba(255,255,255,0.5);
}
.window-button.focused > StWidget {
.window-button.focused > StWidget,
.window-picker-toggle:checked > StWidget {
color: white;
box-shadow: inset 1px 1px 4px rgba(255,255,255,0.7);
}
.window-button.focused:active > StWidget {
.window-button.focused:active > StWidget,
.window-picker-toggle:checked:active > StWidget {
box-shadow: inset 2px 2px 4px rgba(255,255,255,0.7);
}
@@ -70,13 +78,36 @@
height: 24px;
}
.window-list-workspace-indicator {
.window-list-workspace-indicator .status-label-bin {
background-color: rgba(200, 200, 200, .3);
border: 1px solid #cccccc;
padding: 0 3px;
margin: 3px;
}
.window-list-workspace-indicator .workspaces-box {
spacing: 3px;
padding: 3px;
}
.window-list-workspace-indicator > StWidget {
background-color: rgba(200, 200, 200, .3);
border: 1px solid #cccccc;
.window-list-workspace-indicator .workspace {
border: 2px solid #000;
width: 52px;
border-radius: 4px;
background-color: #595959;
}
.window-list-workspace-indicator .workspace.active {
border-color: #fff;
}
.window-list-window-preview {
background-color: #bebebe;
border: 1px solid #828282;
}
.window-list-window-preview.active {
background-color: #d4d4d4;
}
.notification {

View File

@@ -0,0 +1,344 @@
/* exported WindowPicker, WindowPickerToggle */
const { Clutter, GObject, Shell, St } = imports.gi;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const { WorkspacesDisplay } = imports.ui.workspacesView;
const Workspace = imports.ui.workspace;
const { VIGNETTE_BRIGHTNESS } = imports.ui.lightbox;
const {
SIDE_CONTROLS_ANIMATION_TIME,
OverviewAdjustment,
ControlsState,
} = imports.ui.overviewControls;
let MyWorkspacesDisplay = GObject.registerClass(
class MyWorkspacesDisplay extends WorkspacesDisplay {
_init(controls, overviewAdjustment) {
let workspaceManager = global.workspace_manager;
this._overviewAdjustment = overviewAdjustment;
this._workspaceAdjustment = new St.Adjustment({
value: workspaceManager.get_active_workspace_index(),
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: workspaceManager.n_workspaces,
});
this._nWorkspacesChangedId =
workspaceManager.connect('notify::n-workspaces',
this._updateAdjustment.bind(this));
super._init(controls, this._workspaceAdjustment, this._overviewAdjustment);
this._workspaceAdjustment.actor = this;
this.add_constraint(
new Layout.MonitorConstraint({
primary: true,
work_area: true,
}));
}
prepareToEnterOverview(...args) {
if (!this._scrollEventId) {
this._scrollEventId = Main.windowPicker.connect('scroll-event',
this._onScrollEvent.bind(this));
}
super.prepareToEnterOverview(...args);
}
vfunc_hide(...args) {
if (this._scrollEventId > 0)
Main.windowPicker.disconnect(this._scrollEventId);
this._scrollEventId = 0;
super.vfunc_hide(...args);
}
_updateAdjustment() {
let workspaceManager = global.workspace_manager;
this._workspaceAdjustment.set({
upper: workspaceManager.n_workspaces,
value: workspaceManager.get_active_workspace_index(),
});
}
_onDestroy() {
if (this._nWorkspacesChangedId)
global.workspace_manager.disconnect(this._nWorkspacesChangedId);
this._nWorkspacesChangedId = 0;
super._onDestroy();
}
});
const MyWorkspace = GObject.registerClass(
class MyWorkspace extends Workspace.Workspace {
_init(...args) {
super._init(...args);
this._adjChangedId =
this._overviewAdjustment.connect('notify::value', () => {
const { value: progress } = this._overviewAdjustment;
const brightness = 1 - (1 - VIGNETTE_BRIGHTNESS) * progress;
for (const bg of this._background?._backgroundGroup ?? []) {
bg.content.set({
vignette: true,
brightness,
});
}
});
}
_onDestroy() {
super._onDestroy();
if (this._adjChangedId)
this._overviewAdjustment.disconnect(this._adjChangedId);
this._adjChangedId = 0;
}
});
const MyWorkspaceBackground = GObject.registerClass(
class MyWorkspaceBackground extends Workspace.WorkspaceBackground {
_updateBorderRadius() {
}
vfunc_allocate(box) {
this.set_allocation(box);
const themeNode = this.get_theme_node();
const contentBox = themeNode.get_content_box(box);
this._bin.allocate(contentBox);
const [contentWidth, contentHeight] = contentBox.get_size();
const monitor = Main.layoutManager.monitors[this._monitorIndex];
const xRatio = contentWidth / this._workarea.width;
const yRatio = contentHeight / this._workarea.height;
const right = area => area.x + area.width;
const bottom = area => area.y + area.height;
const offsets = {
left: xRatio * (this._workarea.x - monitor.x),
right: xRatio * (right(monitor) - right(this._workarea)),
top: yRatio * (this._workarea.y - monitor.y),
bottom: yRatio * (bottom(monitor) - bottom(this._workarea)),
};
contentBox.set_origin(-offsets.left, -offsets.top);
contentBox.set_size(
offsets.left + contentWidth + offsets.right,
offsets.top + contentHeight + offsets.bottom);
this._backgroundGroup.allocate(contentBox);
}
});
var WindowPicker = GObject.registerClass({
Signals: {
'open-state-changed': { param_types: [GObject.TYPE_BOOLEAN] },
},
}, class extends Clutter.Actor {
_init() {
this._visible = false;
this._modal = false;
this._overlayKeyId = 0;
this._stageKeyPressId = 0;
super._init({ reactive: true });
this._adjustment = new OverviewAdjustment(this);
this.connect('destroy', this._onDestroy.bind(this));
global.bind_property('screen-width',
this, 'width',
GObject.BindingFlags.SYNC_CREATE);
global.bind_property('screen-height',
this, 'height',
GObject.BindingFlags.SYNC_CREATE);
this._workspacesDisplay = new MyWorkspacesDisplay(this, this._adjustment);
this.add_child(this._workspacesDisplay);
Main.uiGroup.insert_child_below(this, global.window_group);
if (!Main.sessionMode.hasOverview) {
this._injectBackgroundShade();
this._overlayKeyId = global.display.connect('overlay-key', () => {
if (!this._visible)
this.open();
else
this.close();
});
}
}
_injectBackgroundShade() {
this._origWorkspace = Workspace.Workspace;
this._origWorkspaceBackground = Workspace.WorkspaceBackground;
Workspace.Workspace = MyWorkspace;
Workspace.WorkspaceBackground = MyWorkspaceBackground;
}
get visible() {
return this._visible;
}
open() {
if (this._visible)
return;
this._visible = true;
if (!this._syncGrab())
return;
this._fakeOverviewVisible(true);
this._workspacesDisplay.prepareToEnterOverview();
Main.overview._animationInProgress = true;
this._adjustment.value = ControlsState.HIDDEN;
this._adjustment.ease(ControlsState.WINDOW_PICKER, {
duration: SIDE_CONTROLS_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => (Main.overview._animationInProgress = false),
});
this._stageKeyPressId = global.stage.connect('key-press-event',
(a, event) => {
let sym = event.get_key_symbol();
if (sym === Clutter.KEY_Escape) {
this.close();
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
});
this.emit('open-state-changed', this._visible);
}
close() {
if (!this._visible)
return;
this._visible = false;
if (!this._syncGrab())
return;
this._workspacesDisplay.prepareToLeaveOverview();
Main.overview._animationInProgress = true;
this._adjustment.ease(ControlsState.HIDDEN, {
duration: SIDE_CONTROLS_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => {
Main.overview._animationInProgress = false;
this._workspacesDisplay.hide();
this._fakeOverviewVisible(false);
},
});
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
this.emit('open-state-changed', this._visible);
}
getWorkspacesBoxForState() {
return this.allocation;
}
_fakeOverviewVisible(visible) {
// Fake overview state for WorkspacesDisplay
Main.overview._visible = visible;
// Hide real windows
Main.layoutManager._inOverview = visible;
Main.layoutManager._updateVisibility();
}
_syncGrab() {
if (this._visible) {
if (this._modal)
return true;
this._modal = Main.pushModal(this, {
actionMode: Shell.ActionMode.OVERVIEW,
});
if (!this._modal) {
this.hide();
return false;
}
} else if (this._modal) {
Main.popModal(this);
this._modal = false;
}
return true;
}
_onDestroy() {
if (this._origWorkspace)
Workspace.Workspace = this._origWorkspace;
if (this._origWorkspaceBackground)
Workspace.WorkspaceBackground = this._origWorkspaceBackground;
if (this._monitorsChangedId)
Main.layoutManager.disconnect(this._monitorsChangedId);
this._monitorsChangedId = 0;
if (this._overlayKeyId)
global.display.disconnect(this._overlayKeyId);
this._overlayKeyId = 0;
if (this._stageKeyPressId)
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
}
});
var WindowPickerToggle = GObject.registerClass(
class WindowPickerToggle extends St.Button {
_init() {
let iconBin = new St.Widget({
layout_manager: new Clutter.BinLayout(),
});
iconBin.add_child(new St.Icon({
icon_name: 'focus-windows-symbolic',
icon_size: 16,
x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
}));
super._init({
style_class: 'window-picker-toggle',
child: iconBin,
visible: !Main.sessionMode.hasOverview,
toggle_mode: true,
});
this.connect('notify::checked', () => {
if (this.checked)
Main.windowPicker.open();
else
Main.windowPicker.close();
});
Main.windowPicker.connect('open-state-changed', () => {
this.checked = Main.windowPicker.visible;
});
}
});

View File

@@ -0,0 +1,439 @@
/* exported WorkspaceIndicator */
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
const DND = imports.ui.dnd;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const _ = ExtensionUtils.gettext;
const TOOLTIP_OFFSET = 6;
const TOOLTIP_ANIMATION_TIME = 150;
const MAX_THUMBNAILS = 6;
let WindowPreview = GObject.registerClass(
class WindowPreview extends St.Button {
_init(window) {
super._init({
style_class: 'window-list-window-preview',
});
this._delegate = this;
DND.makeDraggable(this, { restoreOnSuccess: true });
this._window = window;
this.connect('destroy', this._onDestroy.bind(this));
this._sizeChangedId = this._window.connect('size-changed',
() => this.queue_relayout());
this._positionChangedId = this._window.connect('position-changed',
() => {
this._updateVisible();
this.queue_relayout();
});
this._minimizedChangedId = this._window.connect('notify::minimized',
this._updateVisible.bind(this));
this._focusChangedId = global.display.connect('notify::focus-window',
this._onFocusChanged.bind(this));
this._onFocusChanged();
}
// needed for DND
get metaWindow() {
return this._window;
}
_onDestroy() {
this._window.disconnect(this._sizeChangedId);
this._window.disconnect(this._positionChangedId);
this._window.disconnect(this._minimizedChangedId);
global.display.disconnect(this._focusChangedId);
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_updateVisible() {
const monitor = Main.layoutManager.findIndexForActor(this);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
this.visible = this._window.get_frame_rect().overlap(workArea) &&
this._window.window_type !== Meta.WindowType.DESKTOP &&
this._window.showing_on_its_workspace();
}
});
let WorkspaceLayout = GObject.registerClass(
class WorkspaceLayout extends Clutter.LayoutManager {
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);
}
}
});
let WorkspaceThumbnail = GObject.registerClass(
class WorkspaceThumbnail extends St.Button {
_init(index) {
super._init({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new WorkspaceLayout(),
clip_to_allocation: 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._windowAddedId = this._workspace.connect('window-added',
(ws, window) => {
this._addWindow(window);
});
this._windowRemovedId = this._workspace.connect('window-removed',
(ws, window) => {
this._removeWindow(window);
});
this._restackedId = global.display.connect('restacked',
this._onRestacked.bind(this));
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
acceptDrop(source) {
if (!source.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();
this._workspace.disconnect(this._windowAddedId);
this._workspace.disconnect(this._windowRemovedId);
global.display.disconnect(this._restackedId);
}
});
var WorkspaceIndicator = GObject.registerClass(
class WorkspaceIndicator extends PanelMenu.Button {
_init() {
super._init(0.0, _('Workspace Indicator'), true);
this.setMenu(new PopupMenu.PopupMenu(this, 0.0, St.Side.BOTTOM));
this.add_style_class_name('window-list-workspace-indicator');
this.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_actor(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_actor(this._statusBin);
this._thumbnailsBox = new St.BoxLayout({
style_class: 'workspaces-box',
y_expand: true,
reactive: true,
});
this._thumbnailsBox.connect('scroll-event',
this._onScrollEvent.bind(this));
container.add_actor(this._thumbnailsBox);
this._workspacesItems = [];
this._workspaceManagerSignals = [
workspaceManager.connect('notify::n-workspaces',
this._nWorkspacesChanged.bind(this)),
workspaceManager.connect_after('workspace-switched',
this._onWorkspaceSwitched.bind(this)),
workspaceManager.connect('notify::layout-rows',
this._updateThumbnailVisibility.bind(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._settingsChangedId = this._settings.connect(
'changed::workspace-names', this._updateMenuLabels.bind(this));
}
_onDestroy() {
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
if (this._settingsChangedId) {
this._settings.disconnect(this._settingsChangedId);
this._settingsChangedId = 0;
}
super._onDestroy();
}
_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.NONE);
}
}
_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);
});
if (i === this._currentWorkspace)
item.setOrnament(PopupMenu.Ornament.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_actor(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

@@ -1,3 +0,0 @@
EXTENSION_ID = windowsNavigator
include ../../extension.mk

View File

@@ -1,154 +1,188 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const St = imports.gi.St;
/* exported init */
const { Clutter, Graphene, GObject, St } = imports.gi;
const Main = imports.ui.main;
const OverviewControls = imports.ui.overviewControls;
const Workspace = imports.ui.workspace;
const WorkspacesView = imports.ui.workspacesView;
function injectToFunction(parent, name, func) {
let origin = parent[name];
parent[name] = function() {
let ret;
ret = origin.apply(this, arguments);
if (ret === undefined)
ret = func.apply(this, arguments);
return ret;
const WINDOW_SLOT = 4;
var MyWorkspace = GObject.registerClass(
class MyWorkspace extends Workspace.Workspace {
_init(...args) {
super._init(...args);
if (this.metaWorkspace && this.metaWorkspace.index() < 9) {
this._tip = new St.Label({
style_class: 'extension-windowsNavigator-window-tooltip',
visible: false,
});
this.add_actor(this._tip);
this.connect('notify::scale-x', () => {
this._tip.set_scale(1 / this.scale_x, 1 / this.scale_x);
});
} else {
this._tip = null;
}
}
return origin;
}
let winInjections, workspaceInjections, workViewInjections, createdActors, connectedSignals;
vfunc_allocate(box) {
super.vfunc_allocate(box);
function resetState() {
winInjections = { };
workspaceInjections = { };
workViewInjections = { };
createdActors = [ ];
connectedSignals = [ ];
}
function enable() {
resetState();
Workspace.WindowOverlay.prototype.showTooltip = function() {
this._text.raise_top();
this._text.show();
this._text.text = (this._windowClone.slotId + 1).toString();
if (this._tip)
this._tip.allocate_preferred_size(0, 0);
}
winInjections['showTooltip'] = undefined;
Workspace.WindowOverlay.prototype.hideTooltip = function() {
if (this._text && this._text.visible)
this._text.hide();
}
winInjections['hideTooltip'] = undefined;
Workspace.Workspace.prototype.showTooltip = function() {
if (this._tip == null || this._actualGeometry == null)
showTooltip() {
if (!this._tip)
return;
this._tip.text = (this.metaWorkspace.index() + 1).toString();
this._tip.show();
this.set_child_below_sibling(this._tip, null);
}
// Hand code this instead of using _getSpacingAndPadding
// because that fails on empty workspaces
let node = this.actor.get_theme_node();
let padding = {
left: node.get_padding(St.Side.LEFT),
top: node.get_padding(St.Side.TOP),
bottom: node.get_padding(St.Side.BOTTOM),
right: node.get_padding(St.Side.RIGHT),
hideTooltip() {
if (this._tip)
this._tip.hide();
}
getWindowWithTooltip(id) {
const { layoutManager } = this._container;
const slot = layoutManager._windowSlots[id - 1];
return slot ? slot[WINDOW_SLOT].metaWindow : null;
}
showWindowsTooltips() {
const { layoutManager } = this._container;
for (let i = 0; i < layoutManager._windowSlots.length; i++) {
if (layoutManager._windowSlots[i])
layoutManager._windowSlots[i][WINDOW_SLOT].showTooltip(`${i + 1}`);
}
}
hideWindowsTooltips() {
const { layoutManager } = this._container;
for (let i in layoutManager._windowSlots) {
if (layoutManager._windowSlots[i])
layoutManager._windowSlots[i][WINDOW_SLOT].hideTooltip();
}
}
// overriding _addWindowClone to apply the tooltip patch on the cloned
// windowPreview
_addWindowClone(metaWindow) {
const clone = super._addWindowClone(metaWindow);
// appling the tooltip patch
(function patchPreview() {
this._text = new St.Label({
style_class: 'extension-windowsNavigator-window-tooltip',
visible: false,
});
this._text.add_constraint(new Clutter.BindConstraint({
source: this.windowContainer,
coordinate: Clutter.BindCoordinate.POSITION,
}));
this._text.add_constraint(new Clutter.AlignConstraint({
source: this.windowContainer,
align_axis: Clutter.AlignAxis.X_AXIS,
pivot_point: new Graphene.Point({ x: 0.5, y: -1 }),
factor: this._closeButtonSide === St.Side.LEFT ? 1 : 0,
}));
this._text.add_constraint(new Clutter.AlignConstraint({
source: this.windowContainer,
align_axis: Clutter.AlignAxis.Y_AXIS,
pivot_point: new Graphene.Point({ x: -1, y: 0.5 }),
factor: 0,
}));
this.add_child(this._text);
}).call(clone);
clone.showTooltip = function (text) {
this._text.set({ text });
this._text.show();
};
let area = Workspace.padArea(this._actualGeometry, padding);
this._tip.x = area.x;
this._tip.y = area.y;
this._tip.show();
this._tip.raise_top();
}
workspaceInjections['showTooltip'] = undefined;
clone.hideTooltip = function () {
if (this._text && this._text.visible)
this._text.hide();
};
Workspace.Workspace.prototype.hideTooltip = function() {
if (this._tip == null)
return;
if (!this._tip.get_parent())
return;
this._tip.hide();
return clone;
}
workspaceInjections['hideTooltip'] = undefined;
});
Workspace.Workspace.prototype.getWindowWithTooltip = function(id) {
for (let i = 0; i < this._windows.length; i++) {
if ((this._windows[i].slotId + 1) == id)
return this._windows[i].metaWindow;
}
return null;
var MyWorkspacesView = GObject.registerClass(
class MyWorkspacesView extends WorkspacesView.WorkspacesView {
_init(...args) {
super._init(...args);
this._pickWorkspace = false;
this._pickWindow = false;
this._keyPressEventId =
global.stage.connect('key-press-event', this._onKeyPress.bind(this));
this._keyReleaseEventId =
global.stage.connect('key-release-event', this._onKeyRelease.bind(this));
}
workspaceInjections['getWindowWithTooltip'] = undefined;
Workspace.Workspace.prototype.showWindowsTooltips = function() {
for (let i in this._windowOverlays) {
if (this._windowOverlays[i] != null)
this._windowOverlays[i].showTooltip();
}
_onDestroy() {
super._onDestroy();
global.stage.disconnect(this._keyPressEventId);
global.stage.disconnect(this._keyReleaseEventId);
}
workspaceInjections['showWindowsTooltips'] = undefined;
Workspace.Workspace.prototype.hideWindowsTooltips = function() {
for (let i in this._windowOverlays) {
if (this._windowOverlays[i] != null)
this._windowOverlays[i].hideTooltip();
}
}
workspaceInjections['hideWindowsTooltips'] = undefined;
WorkspacesView.WorkspacesView.prototype._hideTooltips = function() {
if (global.stage.get_key_focus() == global.stage)
_hideTooltips() {
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++)
this._workspaces[i].hideWindowsTooltips();
}
workViewInjections['_hideTooltips'] = undefined;
WorkspacesView.WorkspacesView.prototype._hideWorkspacesTooltips = function() {
_hideWorkspacesTooltips() {
global.stage.set_key_focus(this._prevFocusActor);
this._pickWorkspace = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].hideTooltip();
}
workViewInjections['_hideWorkspacesTooltips'] = undefined;
WorkspacesView.WorkspacesView.prototype._onKeyRelease = function(s, o) {
_onKeyRelease(s, o) {
if (this._pickWindow &&
(o.get_key_symbol() == Clutter.KEY_Alt_L ||
o.get_key_symbol() == Clutter.KEY_Alt_R))
(o.get_key_symbol() === Clutter.KEY_Alt_L ||
o.get_key_symbol() === Clutter.KEY_Alt_R))
this._hideTooltips();
if (this._pickWorkspace &&
(o.get_key_symbol() == Clutter.KEY_Control_L ||
o.get_key_symbol() == Clutter.KEY_Control_R))
(o.get_key_symbol() === Clutter.KEY_Control_L ||
o.get_key_symbol() === Clutter.KEY_Control_R))
this._hideWorkspacesTooltips();
}
workViewInjections['_onKeyRelease'] = undefined;
WorkspacesView.WorkspacesView.prototype._onKeyPress = function(s, o) {
if(Main.overview.viewSelector._activePage != Main.overview.viewSelector._workspacesPage)
_onKeyPress(s, o) {
const { ControlsState } = OverviewControls;
if (this._overviewAdjustment.value !== ControlsState.WINDOW_PICKER)
return false;
if ((o.get_key_symbol() == Clutter.KEY_Alt_L ||
o.get_key_symbol() == Clutter.KEY_Alt_R)
&& !this._pickWorkspace) {
let workspaceManager = global.workspace_manager;
if ((o.get_key_symbol() === Clutter.KEY_Alt_L ||
o.get_key_symbol() === Clutter.KEY_Alt_R) &&
!this._pickWorkspace) {
this._prevFocusActor = global.stage.get_key_focus();
global.stage.set_key_focus(null);
this._active = global.screen.get_active_workspace_index();
this._active = workspaceManager.get_active_workspace_index();
this._pickWindow = true;
this._workspaces[global.screen.get_active_workspace_index()].showWindowsTooltips();
this._workspaces[workspaceManager.get_active_workspace_index()].showWindowsTooltips();
return true;
}
if ((o.get_key_symbol() == Clutter.KEY_Control_L ||
o.get_key_symbol() == Clutter.KEY_Control_R)
&& !this._pickWindow) {
if ((o.get_key_symbol() === Clutter.KEY_Control_L ||
o.get_key_symbol() === Clutter.KEY_Control_R) &&
!this._pickWindow) {
this._prevFocusActor = global.stage.get_key_focus();
global.stage.set_key_focus(null);
this._pickWorkspace = true;
@@ -157,17 +191,17 @@ function enable() {
return true;
}
if (global.stage.get_key_focus() != global.stage)
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) &&
(o.get_key_symbol() == Clutter.KEY_Shift_L ||
o.get_key_symbol() == Clutter.KEY_Shift_R))
(o.get_key_symbol() === Clutter.KEY_Shift_L ||
o.get_key_symbol() === Clutter.KEY_Shift_R))
return true;
if (this._pickWindow) {
if (this._active != global.screen.get_active_workspace_index()) {
if (this._active !== workspaceManager.get_active_workspace_index()) {
this._hideTooltips();
return false;
}
@@ -209,80 +243,28 @@ function enable() {
}
return false;
}
workViewInjections['_onKeyPress'] = undefined;
});
winInjections['_init'] = injectToFunction(Workspace.WindowOverlay.prototype, '_init', function(windowClone, parentActor) {
this._id = null;
createdActors.push(this._text = new St.Label({ style_class: 'extension-windowsNavigator-window-tooltip' }));
this._text.hide();
parentActor.add_actor(this._text);
});
class Extension {
constructor() {
this._origWorkspace = Workspace.Workspace;
this._origWorkspacesView = WorkspacesView.WorkspacesView;
}
winInjections['relayout'] = injectToFunction(Workspace.WindowOverlay.prototype, 'relayout', function(animate) {
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
enable() {
Workspace.Workspace = MyWorkspace;
WorkspacesView.WorkspacesView = MyWorkspacesView;
}
let textX = cloneX - 2;
let textY = cloneY - 2;
this._text.set_position(Math.floor(textX) + 5, Math.floor(textY) + 5);
this._text.raise_top();
});
workspaceInjections['_init'] = injectToFunction(Workspace.Workspace.prototype, '_init', function(metaWorkspace) {
if (metaWorkspace && metaWorkspace.index() < 9) {
createdActors.push(this._tip = new St.Label({ style_class: 'extension-windowsNavigator-window-tooltip',
visible: false }));
this.actor.add_actor(this._tip);
let signalId = this.actor.connect('notify::scale-x', Lang.bind(this, function() {
this._tip.set_scale(1 / this.actor.scale_x, 1 / this.actor.scale_x);
}));
connectedSignals.push({ obj: this.actor, id: signalId });
} else
this._tip = null;
});
workViewInjections['_init'] = injectToFunction(WorkspacesView.WorkspacesView.prototype, '_init', function(width, height, x, y, workspaces) {
this._pickWorkspace = false;
this._pickWindow = false;
this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._onKeyPress));
this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._onKeyRelease));
connectedSignals.push({ obj: global.stage, id: this._keyPressEventId });
connectedSignals.push({ obj: global.stage, id: this._keyReleaseEventId });
});
workViewInjections['_onDestroy'] = injectToFunction(WorkspacesView.WorkspacesView.prototype, '_onDestroy', function() {
global.stage.disconnect(this._keyPressEventId);
global.stage.disconnect(this._keyReleaseEventId);
connectedSignals = [ ];
});
}
function removeInjection(object, injection, name) {
if (injection[name] === undefined)
delete object[name];
else
object[name] = injection[name];
}
function disable() {
let i;
for (i in workspaceInjections)
removeInjection(Workspace.Workspace.prototype, workspaceInjections, i);
for (i in winInjections)
removeInjection(Workspace.WindowOverlay.prototype, winInjections, i);
for (i in workViewInjections)
removeInjection(WorkspacesView.WorkspacesView.prototype, workViewInjections, i);
for each (i in connectedSignals)
i.obj.disconnect(i.id);
for each (i in createdActors)
i.destroy();
resetState();
disable() {
Workspace.Workspace = this._origWorkspace;
WorkspacesView.WorkspacesView = this._origWorkspacesView;
}
}
/**
* @returns {Extension} - the extension's state object
*/
function init() {
/* do nothing */
return new Extension();
}

View File

@@ -0,0 +1,5 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)

View File

@@ -1,5 +0,0 @@
EXTENSION_ID = workspace-indicator
EXTRA_MODULES = prefs.js
include ../../extension.mk

View File

@@ -1,144 +1,461 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init enable disable */
const Gio = imports.gi.Gio;
const Meta = imports.gi.Meta;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
const DND = imports.ui.dnd;
const ExtensionUtils = imports.misc.extensionUtils;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Panel = imports.ui.panel;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _ = ExtensionUtils.gettext;
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
const WORKSPACE_KEY = 'workspace-names';
const WorkspaceIndicator = new Lang.Class({
Name: 'WorkspaceIndicator.WorkspaceIndicator',
Extends: PanelMenu.Button,
const TOOLTIP_OFFSET = 6;
const TOOLTIP_ANIMATION_TIME = 150;
_init: function(){
this.parent(0.0, _("Workspace Indicator"));
const MAX_THUMBNAILS = 6;
this._currentWorkspace = global.screen.get_active_workspace().index();
this.statusLabel = new St.Label({ y_align: Clutter.ActorAlign.CENTER,
text: this._labelText() });
let WindowPreview = GObject.registerClass(
class WindowPreview extends St.Button {
_init(window) {
super._init({
style_class: 'workspace-indicator-window-preview',
});
this.actor.add_actor(this.statusLabel);
this._delegate = this;
DND.makeDraggable(this, { restoreOnSuccess: true });
this.workspacesItems = [];
this._workspaceSection = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(this._workspaceSection);
this._window = window;
this._screenSignals = [];
this._screenSignals.push(global.screen.connect_after('workspace-added', Lang.bind(this,this._createWorkspacesSection)));
this._screenSignals.push(global.screen.connect_after('workspace-removed', Lang.bind(this,this._createWorkspacesSection)));
this._screenSignals.push(global.screen.connect_after('workspace-switched', Lang.bind(this,this._updateIndicator)));
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this._createWorkspacesSection();
this._sizeChangedId = this._window.connect('size-changed',
() => this.queue_relayout());
this._positionChangedId = this._window.connect('position-changed',
() => {
this._updateVisible();
this.queue_relayout();
});
this._minimizedChangedId = this._window.connect('notify::minimized',
this._updateVisible.bind(this));
//styling
this.statusLabel.add_style_class_name('panel-workspace-indicator');
this._focusChangedId = global.display.connect('notify::focus-window',
this._onFocusChanged.bind(this));
this._onFocusChanged();
}
// needed for DND
get metaWindow() {
return this._window;
}
_onDestroy() {
this._window.disconnect(this._sizeChangedId);
this._window.disconnect(this._positionChangedId);
this._window.disconnect(this._minimizedChangedId);
global.display.disconnect(this._focusChangedId);
}
_onFocusChanged() {
if (global.display.focus_window === this._window)
this.add_style_class_name('active');
else
this.remove_style_class_name('active');
}
_updateVisible() {
const monitor = Main.layoutManager.findIndexForActor(this);
const workArea = Main.layoutManager.getWorkAreaForMonitor(monitor);
this.visible = this._window.get_frame_rect().overlap(workArea) &&
this._window.window_type !== Meta.WindowType.DESKTOP &&
this._window.showing_on_its_workspace();
}
});
let WorkspaceLayout = GObject.registerClass(
class WorkspaceLayout extends Clutter.LayoutManager {
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);
}
}
});
let WorkspaceThumbnail = GObject.registerClass(
class WorkspaceThumbnail extends St.Button {
_init(index) {
super._init({
style_class: 'workspace',
child: new Clutter.Actor({
layout_manager: new WorkspaceLayout(),
clip_to_allocation: 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._windowAddedId = this._workspace.connect('window-added',
(ws, window) => {
this._addWindow(window);
});
this._windowRemovedId = this._workspace.connect('window-removed',
(ws, window) => {
this._removeWindow(window);
});
this._restackedId = global.display.connect('restacked',
this._onRestacked.bind(this));
this._workspace.list_windows().forEach(w => this._addWindow(w));
this._onRestacked();
}
acceptDrop(source) {
if (!source.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();
this._workspace.disconnect(this._windowAddedId);
this._workspace.disconnect(this._windowRemovedId);
global.display.disconnect(this._restackedId);
}
});
let WorkspaceIndicator = GObject.registerClass(
class WorkspaceIndicator extends PanelMenu.Button {
_init() {
super._init(0.0, _('Workspace Indicator'));
let container = new St.Widget({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
});
this.add_actor(container);
let workspaceManager = global.workspace_manager;
this._currentWorkspace = workspaceManager.get_active_workspace_index();
this._statusLabel = new St.Label({
style_class: 'panel-workspace-indicator',
y_align: Clutter.ActorAlign.CENTER,
text: this._labelText(),
});
container.add_actor(this._statusLabel);
this._thumbnailsBox = new St.BoxLayout({
style_class: 'panel-workspace-indicator-box',
y_expand: true,
reactive: true,
});
container.add_actor(this._thumbnailsBox);
this._workspacesItems = [];
this._workspaceSection = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(this._workspaceSection);
this._workspaceManagerSignals = [
workspaceManager.connect_after('notify::n-workspaces',
this._nWorkspacesChanged.bind(this)),
workspaceManager.connect_after('workspace-switched',
this._onWorkspaceSwitched.bind(this)),
workspaceManager.connect('notify::layout-rows',
this._updateThumbnailVisibility.bind(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._settingsChangedId = this._settings.connect('changed::' + WORKSPACE_KEY, Lang.bind(this, this._createWorkspacesSection));
},
this._settingsChangedId = this._settings.connect(
`changed::${WORKSPACE_KEY}`,
this._updateMenuLabels.bind(this));
}
destroy: function() {
for (let i = 0; i < this._screenSignals.length; i++)
global.screen.disconnect(this._screenSignals[i]);
_onDestroy() {
for (let i = 0; i < this._workspaceManagerSignals.length; i++)
global.workspace_manager.disconnect(this._workspaceManagerSignals[i]);
if (this._settingsChangedId) {
this._settings.disconnect(this._settingsChangedId);
this._settingsChangedId = 0;
}
this.parent();
},
Main.panel.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
_updateIndicator: function() {
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.NONE);
this._currentWorkspace = global.screen.get_active_workspace().index();
this.workspacesItems[this._currentWorkspace].setOrnament(PopupMenu.Ornament.DOT);
super._onDestroy();
}
this.statusLabel.set_text(this._labelText());
},
_updateThumbnailVisibility() {
const { workspaceManager } = global;
const vertical = workspaceManager.layout_rows === -1;
const useMenu =
vertical || workspaceManager.n_workspaces > MAX_THUMBNAILS;
this.reactive = useMenu;
_labelText : function(workspaceIndex) {
if(workspaceIndex == undefined) {
workspaceIndex = this._currentWorkspace;
return (workspaceIndex + 1).toString();
}
return Meta.prefs_get_workspace_name(workspaceIndex);
},
this._statusLabel.visible = useMenu;
this._thumbnailsBox.visible = !useMenu;
_createWorkspacesSection : function() {
this._workspaceSection.removeAll();
this.workspacesItems = [];
this._currentWorkspace = global.screen.get_active_workspace().index();
// 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);
}
let i = 0;
for(; i < global.screen.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;
let self = this;
this.workspacesItems[i].connect('activate', Lang.bind(this, function(actor, event) {
this._activate(actor.workspaceId);
}));
_onWorkspaceSwitched() {
this._currentWorkspace = global.workspace_manager.get_active_workspace_index();
if (i == this._currentWorkspace)
this.workspacesItems[i].setOrnament(PopupMenu.Ornament.DOT);
}
this._updateMenuOrnament();
this._updateActiveThumbnail();
this.statusLabel.set_text(this._labelText());
},
this._statusLabel.set_text(this._labelText());
}
_activate : function (index) {
if(index >= 0 && index < global.screen.n_workspaces) {
let metaWorkspace = global.screen.get_workspace_by_index(index);
metaWorkspace.activate(global.get_current_time());
}
},
_nWorkspacesChanged() {
this._createWorkspacesSection();
this._updateThumbnails();
this._updateThumbnailVisibility();
}
_onScrollEvent : function(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;
}
_updateMenuOrnament() {
for (let i = 0; i < this._workspacesItems.length; i++) {
this._workspacesItems[i].setOrnament(i === this._currentWorkspace
? PopupMenu.Ornament.DOT
: PopupMenu.Ornament.NONE);
}
}
let newIndex = global.screen.get_active_workspace().index() + diff;
this._activate(newIndex);
},
_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);
});
if (i === this._currentWorkspace)
this._workspacesItems[i].setOrnament(PopupMenu.Ornament.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_actor(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);
}
});
function init(meta) {
Convenience.initTranslations();
/** */
function init() {
ExtensionUtils.initTranslations();
}
let _indicator;
/** */
function enable() {
_indicator = new WorkspaceIndicator;
_indicator = new WorkspaceIndicator();
Main.panel.addToStatusArea('workspace-indicator', _indicator);
}
/** */
function disable() {
_indicator.destroy();
}

View File

@@ -0,0 +1,7 @@
extension_data += configure_file(
input: metadata_name + '.in',
output: metadata_name,
configuration: metadata_conf
)
extension_sources += files('prefs.js')

View File

@@ -1,219 +1,221 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
/* exported init buildPrefsWidget */
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Gettext = imports.gettext.domain('gnome-shell-extensions');
const _ = Gettext.gettext;
const N_ = function(e) { return e };
const { Gio, GLib, GObject, Gtk, Pango } = imports.gi;
const ExtensionUtils = imports.misc.extensionUtils;
const Me = ExtensionUtils.getCurrentExtension();
const Convenience = Me.imports.convenience;
const _ = ExtensionUtils.gettext;
const N_ = e => e;
const WORKSPACE_SCHEMA = 'org.gnome.desktop.wm.preferences';
const WORKSPACE_KEY = 'workspace-names';
const WorkspaceNameModel = new GObject.Class({
Name: 'WorkspaceIndicator.WorkspaceNameModel',
GTypeName: 'WorkspaceNameModel',
Extends: Gtk.ListStore,
const WorkspaceSettingsWidget = GObject.registerClass(
class WorkspaceSettingsWidget extends Gtk.ScrolledWindow {
_init() {
super._init({
hscrollbar_policy: Gtk.PolicyType.NEVER,
});
Columns: {
LABEL: 0,
},
const box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
halign: Gtk.Align.CENTER,
spacing: 12,
margin_top: 36,
margin_bottom: 36,
margin_start: 36,
margin_end: 36,
});
this.set_child(box);
_init: function(params) {
this.parent(params);
this.set_column_types([GObject.TYPE_STRING]);
box.append(new Gtk.Label({
label: '<b>%s</b>'.format(_('Workspace Names')),
use_markup: true,
halign: Gtk.Align.START,
}));
this._settings = new Gio.Settings({ schema_id: WORKSPACE_SCHEMA });
//this._settings.connect('changed::workspace-names', Lang.bind(this, this._reloadFromSettings));
this._list = new Gtk.ListBox({
selection_mode: Gtk.SelectionMode.NONE,
valign: Gtk.Align.START,
show_separators: true,
});
this._list.connect('row-activated', (l, row) => row.edit());
box.append(this._list);
this._reloadFromSettings();
const context = this._list.get_style_context();
const cssProvider = new Gtk.CssProvider();
cssProvider.load_from_data(
'list { min-width: 25em; }');
// overriding class closure doesn't work, because GtkTreeModel
// plays tricks with marshallers and class closures
this.connect('row-changed', Lang.bind(this, this._onRowChanged));
this.connect('row-inserted', Lang.bind(this, this._onRowInserted));
this.connect('row-deleted', Lang.bind(this, this._onRowDeleted));
},
context.add_provider(cssProvider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
context.add_class('frame');
_reloadFromSettings: function() {
if (this._preventChanges)
return;
this._preventChanges = true;
this._list.append(new NewWorkspaceRow());
let newNames = this._settings.get_strv(WORKSPACE_KEY);
this._actionGroup = new Gio.SimpleActionGroup();
this._list.insert_action_group('workspaces', this._actionGroup);
let i = 0;
let [ok, iter] = this.get_iter_first();
while (ok && i < newNames.length) {
this.set(iter, [this.Columns.LABEL], [newNames[i]]);
let action;
action = new Gio.SimpleAction({ name: 'add' });
action.connect('activate', () => {
const names = this._settings.get_strv(WORKSPACE_KEY);
this._settings.set_strv(WORKSPACE_KEY, [
...names,
_('Workspace %d').format(names.length + 1),
]);
});
this._actionGroup.add_action(action);
ok = this.iter_next(iter);
i++;
}
action = new Gio.SimpleAction({
name: 'remove',
parameter_type: new GLib.VariantType('s'),
});
action.connect('activate', (a, param) => {
const removed = param.deepUnpack();
this._settings.set_strv(WORKSPACE_KEY,
this._settings.get_strv(WORKSPACE_KEY)
.filter(name => name !== removed));
});
this._actionGroup.add_action(action);
while (ok)
ok = this.remove(iter);
action = new Gio.SimpleAction({ name: 'update' });
action.connect('activate', () => {
const names = this._getWorkspaceRows().map(row => row.name);
this._settings.set_strv(WORKSPACE_KEY, names);
});
this._actionGroup.add_action(action);
for ( ; i < newNames.length; i++) {
iter = this.append();
this.set(iter, [this.Columns.LABEL], [newNames[i]]);
}
this._settings = new Gio.Settings({
schema_id: WORKSPACE_SCHEMA,
});
this._settings.connect(`changed::${WORKSPACE_KEY}`,
this._sync.bind(this));
this._sync();
}
this._preventChanges = false;
},
_getWorkspaceRows() {
return [...this._list].filter(row => row.name);
}
_onRowChanged: function(self, path, iter) {
if (this._preventChanges)
return;
this._preventChanges = true;
_sync() {
const rows = this._getWorkspaceRows();
let index = path.get_indices()[0];
let names = this._settings.get_strv(WORKSPACE_KEY);
const oldNames = rows.map(row => row.name);
const newNames = this._settings.get_strv(WORKSPACE_KEY);
if (index >= names.length) {
// fill with blanks
for (let i = names.length; i <= index; i++)
names[i] = '';
}
const removed = oldNames.filter(n => !newNames.includes(n));
const added = newNames.filter(n => !oldNames.includes(n));
names[index] = this.get_value(iter, this.Columns.LABEL);
this._settings.set_strv(WORKSPACE_KEY, names);
this._preventChanges = false;
},
_onRowInserted: function(self, path, iter) {
if (this._preventChanges)
return;
this._preventChanges = true;
let index = path.get_indices()[0];
let names = this._settings.get_strv(WORKSPACE_KEY);
let label = this.get_value(iter, this.Columns.LABEL) || '';
names.splice(index, 0, label);
this._settings.set_strv(WORKSPACE_KEY, names);
this._preventChanges = false;
},
_onRowDeleted: function(self, path) {
if (this._preventChanges)
return;
this._preventChanges = true;
let index = path.get_indices()[0];
let names = this._settings.get_strv(WORKSPACE_KEY);
if (index >= names.length)
return;
names.splice(index, 1);
// compact the array
for (let i = names.length -1; i >= 0 && !names[i]; i++)
names.pop();
this._settings.set_strv(WORKSPACE_KEY, names);
this._preventChanges = false;
},
});
const WorkspaceSettingsWidget = new GObject.Class({
Name: 'WorkspaceIndicator.WorkspaceSettingsWidget',
GTypeName: 'WorkspaceSettingsWidget',
Extends: Gtk.Grid,
_init: function(params) {
this.parent(params);
this.margin = 12;
this.orientation = Gtk.Orientation.VERTICAL;
this.add(new Gtk.Label({ label: '<b>' + _("Workspace Names") + '</b>',
use_markup: true, margin_bottom: 6,
hexpand: true, halign: Gtk.Align.START }));
let scrolled = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN });
scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.add(scrolled);
this._store = new WorkspaceNameModel();
this._treeView = new Gtk.TreeView({ model: this._store,
headers_visible: false,
reorderable: true,
hexpand: true,
vexpand: true
});
let column = new Gtk.TreeViewColumn({ title: _("Name") });
let renderer = new Gtk.CellRendererText({ editable: true });
renderer.connect('edited', Lang.bind(this, this._cellEdited));
column.pack_start(renderer, true);
column.add_attribute(renderer, 'text', this._store.Columns.LABEL);
this._treeView.append_column(column);
scrolled.add(this._treeView);
let toolbar = new Gtk.Toolbar({ icon_size: Gtk.IconSize.SMALL_TOOLBAR });
toolbar.get_style_context().add_class(Gtk.STYLE_CLASS_INLINE_TOOLBAR);
let newButton = new Gtk.ToolButton({ icon_name: 'list-add-symbolic' });
newButton.connect('clicked', Lang.bind(this, this._newClicked));
toolbar.add(newButton);
let delButton = new Gtk.ToolButton({ icon_name: 'list-remove-symbolic' });
delButton.connect('clicked', Lang.bind(this, this._delClicked));
toolbar.add(delButton);
let selection = this._treeView.get_selection();
selection.connect('changed',
function() {
delButton.sensitive = selection.count_selected_rows() > 0;
});
delButton.sensitive = selection.count_selected_rows() > 0;
this.add(toolbar);
},
_cellEdited: function(renderer, path, new_text) {
let [ok, iter] = this._store.get_iter_from_string(path);
if (ok)
this._store.set(iter, [this._store.Columns.LABEL], [new_text]);
},
_newClicked: function() {
let iter = this._store.append();
let index = this._store.get_path(iter).get_indices()[0];
let label = _("Workspace %d").format(index + 1);
this._store.set(iter, [this._store.Columns.LABEL], [label]);
},
_delClicked: function() {
let [any, model, iter] = this._treeView.get_selection().get_selected();
if (any)
this._store.remove(iter);
removed.forEach(n => this._list.remove(rows.find(r => r.name === n)));
added.forEach(n => {
this._list.insert(new WorkspaceRow(n), newNames.indexOf(n));
});
}
});
const WorkspaceRow = GObject.registerClass(
class WorkspaceRow extends Gtk.ListBoxRow {
_init(name) {
super._init({ name });
const controller = new Gtk.ShortcutController();
controller.add_shortcut(new Gtk.Shortcut({
trigger: Gtk.ShortcutTrigger.parse_string('Escape'),
action: Gtk.CallbackAction.new(this._stopEdit.bind(this)),
}));
this.add_controller(controller);
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',
action_target: new GLib.Variant('s', name),
icon_name: 'edit-delete-symbolic',
});
box.append(button);
this._entry = new Gtk.Entry({
max_width_chars: 25,
});
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.name = this._entry.text;
this._stopEdit();
});
this._entry.connect('notify::has-focus', () => {
if (this._entry.has_focus)
return;
this._stopEdit();
});
this.connect('notify::name', () => {
button.action_target = new GLib.Variant('s', this.name);
this.activate_action('workspaces.update', null);
});
}
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';
}
});
const NewWorkspaceRow = GObject.registerClass(
class NewWorkspaceRow extends Gtk.ListBoxRow {
_init() {
super._init({
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')]);
}
});
/** */
function init() {
Convenience.initTranslations();
ExtensionUtils.initTranslations();
}
/**
* @returns {Gtk.Widget} - the prefs widget
*/
function buildPrefsWidget() {
let widget = new WorkspaceSettingsWidget();
widget.show_all();
return widget;
return new WorkspaceSettingsWidget();
}

View File

@@ -1,5 +1,28 @@
.panel-workspace-indicator {
padding: 0 8px;
background-color: rgba(200, 200, 200, .5);
border: 1px solid #cccccc;
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

@@ -15,7 +15,7 @@ and will be picked automatically at next login.
<homepage rdf:resource="https://wiki.gnome.org/Projects/GnomeShell/Extensions" />
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell-extensions/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell&amp;component=extensions" />
<bug-database rdf:resource="https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>JavaScript</programming-language>
@@ -34,4 +34,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>

View File

@@ -1,12 +0,0 @@
extensionurl = http://git.gnome.org/gnome-shell-extensions
# Change these to modify how installation is performed
topextensiondir = $(datadir)/gnome-shell/extensions
extensionbase = @gnome-shell-extensions.gcampax.github.com
gschemabase = org.gnome.shell.extensions
uuid = $(EXTENSION_ID)$(extensionbase)
gschemaname = $(gschemabase).$(EXTENSION_ID)
extensiondir = $(topextensiondir)/$(uuid)

View File

@@ -1,93 +0,0 @@
/* -*- mode: js; js-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Copyright (c) 2011-2012, Giovanni Campagna <scampa.giovanni@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the GNOME nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const Gettext = imports.gettext;
const Gio = imports.gi.Gio;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
/**
* initTranslations:
* @domain: (optional): the gettext domain to use
*
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
function initTranslations(domain) {
let extension = ExtensionUtils.getCurrentExtension();
domain = domain || extension.metadata['gettext-domain'];
// check if this extension was built with "make zip-file", and thus
// has the locale files in a subfolder
// otherwise assume that extension has been installed in the
// same prefix as gnome-shell
let localeDir = extension.dir.get_child('locale');
if (localeDir.query_exists(null))
Gettext.bindtextdomain(domain, localeDir.get_path());
else
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
}
/**
* getSettings:
* @schema: (optional): the GSettings schema id
*
* Builds and return a GSettings schema for @schema, using schema files
* in extensionsdir/schemas. If @schema is not provided, it is taken from
* metadata['settings-schema'].
*/
function getSettings(schema) {
let extension = ExtensionUtils.getCurrentExtension();
schema = schema || extension.metadata['settings-schema'];
const GioSSS = Gio.SettingsSchemaSource;
// check if this extension was built with "make zip-file", and thus
// has the schema files in a subfolder
// otherwise assume that extension has been installed in the
// same prefix as gnome-shell (and therefore schemas are available
// in the standard folders)
let schemaDir = extension.dir.get_child('schemas');
let schemaSource;
if (schemaDir.query_exists(null))
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(),
false);
else
schemaSource = GioSSS.get_default();
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj)
throw new Error('Schema ' + schema + ' could not be found for extension '
+ extension.metadata.uuid + '. Please check your installation.');
return new Gio.Settings({ settings_schema: schemaObj });
}

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