Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53fc6c795b | |||
| 0e37feff15 | |||
| e488482a2c | |||
| c4b40926bd | |||
| da622f3f61 | |||
| 3c5b893830 |
@@ -1,3 +0,0 @@
|
|||||||
extends:
|
|
||||||
- ./lint/eslintrc-gjs.yml
|
|
||||||
- ./lint/eslintrc-shell.yml
|
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
Makefile.in.in
|
||||||
|
configure
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache/
|
||||||
|
po/gnome-shell-extensions.pot
|
||||||
|
po/POTFILES
|
||||||
|
po/stamp-it
|
||||||
|
staging/
|
||||||
|
|
||||||
|
*~
|
||||||
|
*.gmo
|
||||||
|
metadata.json
|
||||||
|
*.gschema.xml
|
||||||
|
*.gschema.valid
|
||||||
-170
@@ -1,170 +0,0 @@
|
|||||||
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"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- pre_review
|
|
||||||
- prepare
|
|
||||||
- review
|
|
||||||
- build
|
|
||||||
- deploy
|
|
||||||
|
|
||||||
default:
|
|
||||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/fedora/35:2022-02-18.0
|
|
||||||
# Cancel jobs if newer commits are pushed to the branch
|
|
||||||
interruptible: true
|
|
||||||
# Auto-retry jobs in case of infra failures
|
|
||||||
retry:
|
|
||||||
max: 1
|
|
||||||
when:
|
|
||||||
- 'runner_system_failure'
|
|
||||||
- 'stuck_or_timeout_failure'
|
|
||||||
- 'scheduler_failure'
|
|
||||||
- 'api_failure'
|
|
||||||
|
|
||||||
variables:
|
|
||||||
FDO_UPSTREAM_REPO: GNOME/gnome-shell-extensions
|
|
||||||
LINT_LOG: "eslint-report.xml"
|
|
||||||
|
|
||||||
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:
|
|
||||||
- gjs-check-syntax
|
|
||||||
|
|
||||||
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
|
|
||||||
variables:
|
|
||||||
GIT_SUBMODULE_STRATEGY: normal
|
|
||||||
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
|
|
||||||
variables:
|
|
||||||
GIT_SUBMODULE_STRATEGY: normal
|
|
||||||
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'
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
--- 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
@@ -1,31 +0,0 @@
|
|||||||
## 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
|
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||||
|
|
||||||
|
SUBDIRS = extensions po
|
||||||
|
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS = --enable-extensions=all
|
||||||
|
|
||||||
|
include include.mk
|
||||||
|
|
||||||
|
zip-file: all
|
||||||
|
-rm -fR $(builddir)/_build
|
||||||
|
-rm -fR $(builddir)/zip-files
|
||||||
|
mkdir $(builddir)/_build; \
|
||||||
|
mkdir $(builddir)/zip-files; \
|
||||||
|
$(MAKE) install DESTDIR="`pwd`/_build"; \
|
||||||
|
for i in $(ENABLED_EXTENSIONS); do \
|
||||||
|
mv "`pwd`/_build/$(topextensiondir)/$${i}$(extensionbase)" "`pwd`/_build/"; \
|
||||||
|
cp -r "`pwd`/_build/$(datadir)/locale" "`pwd`/_build/$${i}$(extensionbase)"; \
|
||||||
|
if [ -f "`pwd`/_build/$(datadir)/glib-2.0/schemas/$(gschemabase).$${i}.gschema.xml" ]; then \
|
||||||
|
mkdir "`pwd`/_build/$${i}$(extensionbase)/schemas"; \
|
||||||
|
mv "`pwd`/_build/$(datadir)/glib-2.0/schemas/$(gschemabase).$${i}.gschema.xml" "`pwd`/_build/$${i}$(extensionbase)/schemas"; \
|
||||||
|
glib-compile-schemas "`pwd`/_build/$${i}$(extensionbase)/schemas"; \
|
||||||
|
fi; \
|
||||||
|
(cd "`pwd`/_build/$${i}$(extensionbase)"; \
|
||||||
|
zip -qr "$(abs_builddir)/zip-files/$${i}$(extensionbase).shell-extension.zip" .; \
|
||||||
|
); \
|
||||||
|
done
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
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"). Also, since extensions are built from many
|
||||||
|
individual contributors, we cannot guarantee stability or quality for any
|
||||||
|
specific extension.
|
||||||
|
For these reasons, distributions are advised to avoid installing or packaging
|
||||||
|
this module by defaul.
|
||||||
|
|
||||||
|
For more information about GNOME Shell Extensions
|
||||||
|
http://live.gnome.org/GnomeShell/Extensions
|
||||||
|
|
||||||
|
For general information about GNOME Shell
|
||||||
|
http://live.gnome.org/GnomeShell
|
||||||
|
|
||||||
|
Bugs should be reported at http://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.
|
||||||
|
|
||||||
|
alternative-status-menu
|
||||||
|
|
||||||
|
For those who want a power off item visible at all the time, replaces GNOME Shell
|
||||||
|
status menu with one featuring separate Suspend and Power Off. Adds the ability to
|
||||||
|
hibernate as well.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
systemMonitor
|
||||||
|
|
||||||
|
An message tray indicator showing CPU and memory loads.
|
||||||
|
|
||||||
|
user-theme
|
||||||
|
|
||||||
|
Loads a shell theme from ~/.themes/<name>/gnome-shell.
|
||||||
|
|
||||||
|
windowsNavigator
|
||||||
|
|
||||||
|
Allow keyboard selection of windows and workspaces in overlay mode.
|
||||||
|
|
||||||
|
xrandr-indicator
|
||||||
|
|
||||||
|
Replace the GTK+ based indicator from gnome-settings-daemon with
|
||||||
|
a native one. Lets the user rotate the laptop monitor and open
|
||||||
|
display preferences quickly.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
# 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/
|
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Run this to generate all the initial makefiles, etc.
|
||||||
|
|
||||||
|
srcdir=`dirname $0`
|
||||||
|
test -z "$srcdir" && srcdir=.
|
||||||
|
|
||||||
|
PKG_NAME="gnome-shell-extensions"
|
||||||
|
|
||||||
|
test -f $srcdir/configure.ac || {
|
||||||
|
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
|
||||||
|
echo " top-level gnome-shell-extensions directory"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
install-sh
|
||||||
|
mkinstalldirs
|
||||||
|
missing
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
AC_PREREQ(2.63)
|
||||||
|
AC_INIT([gnome-shell-extensions],[3.2.2],[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-bzip2 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.])
|
||||||
|
IT_PROG_INTLTOOL(0.26)
|
||||||
|
|
||||||
|
PKG_PROG_PKG_CONFIG([0.22])
|
||||||
|
|
||||||
|
GLIB_GSETTINGS
|
||||||
|
|
||||||
|
dnl keep this in alphabetic order
|
||||||
|
dnl by default, install only extensions that do not change completely the shell experience,
|
||||||
|
dnl that don't require GSettings and that don't require external packages for typelibs
|
||||||
|
dnl (so basically only menus, status icons, search providers, overview tabs, message tray sources, etc.)
|
||||||
|
DEFAULT_EXTENSIONS="alternative-status-menu apps-menu dock drive-menu gajim places-menu windowsNavigator workspace-indicator"
|
||||||
|
ALL_EXTENSIONS="$DEFAULT_EXTENSIONS alternate-tab auto-move-windows example native-window-placement systemMonitor user-theme xrandr-indicator"
|
||||||
|
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 all extensions that can be installed in the home directory and have no external depedencies.
|
||||||
|
Use "all" to enable all available extensions.])],
|
||||||
|
[],
|
||||||
|
[enable_extensions=$DEFAULT_EXTENSIONS]
|
||||||
|
)
|
||||||
|
if test x$enable_extensions = xall; then
|
||||||
|
enable_extensions="$ALL_EXTENSIONS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
ENABLED_EXTENSIONS=
|
||||||
|
for e in $enable_extensions; do
|
||||||
|
case $e in
|
||||||
|
systemMonitor)
|
||||||
|
PKG_CHECK_MODULES(GTOP, libgtop-2.0 >= 2.28.3,
|
||||||
|
[ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"],
|
||||||
|
[AC_MSG_WARN([libgtop-2.0 not found, disabling systemMonitor])])
|
||||||
|
;;
|
||||||
|
xrandr-indicator)
|
||||||
|
PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0 >= 2.91.6,
|
||||||
|
[ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"],
|
||||||
|
[AC_MSG_WARN([gnome-desktop-3.0 not found, disabling xrandr-indicator])])
|
||||||
|
;;
|
||||||
|
dnl keep this in alphabetic order
|
||||||
|
alternate-tab|alternative-status-menu|apps-menu|auto-move-windows|dock|drive-menu|example|gajim|native-window-placement|places-menu|user-theme|windowsNavigator|workspace-indicator)
|
||||||
|
ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_MSG_ERROR([invalid extension $e])
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
AC_SUBST(ENABLED_EXTENSIONS, [$ENABLED_EXTENSIONS])
|
||||||
|
|
||||||
|
dnl Please keep this sorted alphabetically
|
||||||
|
AC_CONFIG_FILES([
|
||||||
|
extensions/alternate-tab/Makefile
|
||||||
|
extensions/alternative-status-menu/Makefile
|
||||||
|
extensions/apps-menu/Makefile
|
||||||
|
extensions/auto-move-windows/Makefile
|
||||||
|
extensions/dock/Makefile
|
||||||
|
extensions/drive-menu/Makefile
|
||||||
|
extensions/example/Makefile
|
||||||
|
extensions/gajim/Makefile
|
||||||
|
extensions/native-window-placement/Makefile
|
||||||
|
extensions/places-menu/Makefile
|
||||||
|
extensions/systemMonitor/Makefile
|
||||||
|
extensions/user-theme/Makefile
|
||||||
|
extensions/windowsNavigator/Makefile
|
||||||
|
extensions/workspace-indicator/Makefile
|
||||||
|
extensions/xrandr-indicator/Makefile
|
||||||
|
extensions/Makefile
|
||||||
|
Makefile
|
||||||
|
po/Makefile.in
|
||||||
|
])
|
||||||
|
AC_OUTPUT
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
[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']
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
To update the gnome-shell-sass submodule to latest upstream commit:
|
|
||||||
git submodule update --rebase
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 100 KiB |
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"parentMode": "user",
|
|
||||||
"stylesheetName": "gnome-classic.css",
|
|
||||||
"hasOverview": false,
|
|
||||||
"showWelcomeDialog": false,
|
|
||||||
"enabledExtensions": [@CLASSIC_EXTENSIONS@],
|
|
||||||
"panel": { "left": ["appMenu"],
|
|
||||||
"center": [],
|
|
||||||
"right": ["a11y", "keyboard", "dateMenu", "quickSettings"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
@import url("gnome-classic.css");
|
|
||||||
|
|
||||||
stage {
|
|
||||||
-st-icon-style: symbolic;
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[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
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[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
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
Name=GNOME Classic
|
|
||||||
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
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* Use the gnome-shell theme, but with light colors */
|
|
||||||
$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.solid {
|
|
||||||
font-weight: normal;
|
|
||||||
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
|
|
||||||
use the top border color for any border, so we
|
|
||||||
need to set it even if all we want is a bottom
|
|
||||||
border */
|
|
||||||
border-bottom: 1px solid #666;
|
|
||||||
app-icon-bottom-clip: 0px;
|
|
||||||
&:overview {
|
|
||||||
background-color: #000;
|
|
||||||
background-gradient-end: #000;
|
|
||||||
border-top-color: #000;
|
|
||||||
border-bottom: 1px solid #000;
|
|
||||||
.panel-button { color: #fff; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-button {
|
|
||||||
-natural-hpadding: 8px;
|
|
||||||
-minimum-hpadding: 4px;
|
|
||||||
font-weight: normal;
|
|
||||||
color: $fg_color;
|
|
||||||
text-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,
|
|
||||||
.panel-corner:active,
|
|
||||||
.panel-corner:overview,
|
|
||||||
.panel-corner:focus {
|
|
||||||
-panel-corner-radius: 0;
|
|
||||||
}
|
|
||||||
&.lock-screen,
|
|
||||||
&.unlock-screen,
|
|
||||||
&.login-screen {
|
|
||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#appMenu {
|
|
||||||
spinner-image: url("classic-process-working.svg");
|
|
||||||
.panel-status-menu-box { padding: 0; }
|
|
||||||
}
|
|
||||||
.tile-preview-left.on-primary,
|
|
||||||
.tile-preview-right.on-primary,
|
|
||||||
.tile-preview-left.tile-preview-right.on-primary {
|
|
||||||
/* keep in sync with -panel-corner-radius */
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
Version 2, June 1991
|
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org>
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
|
||||||
of this license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Preamble
|
|
||||||
|
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Library General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Library General
|
|
||||||
Public License instead of this License.
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# GNOME Shell Sass
|
|
||||||
GNOME Shell Sass is a project intended to allow the sharing of the
|
|
||||||
theme sources in sass between gnome-shell and other projects like
|
|
||||||
gnome-shell-extensions.
|
|
||||||
|
|
||||||
Any changes should be done in the [GNOME Shell subtree][shell-subtree]
|
|
||||||
and not the stand-alone [gnome-shell-sass repository][sass-repo]. They
|
|
||||||
will then be synchronized periodically before releases.
|
|
||||||
|
|
||||||
## License
|
|
||||||
GNOME Shell Sass is distributed under the terms of the GNU General Public
|
|
||||||
License, version 2 or later. See the [COPYING][license] file for details.
|
|
||||||
|
|
||||||
[shell-subtree]: https://gitlab.gnome.org/GNOME/gnome-shell/tree/HEAD/data/theme/gnome-shell-sass
|
|
||||||
[sass-repo]: https://gitlab.gnome.org/GNOME/gnome-shell-sass
|
|
||||||
[license]: COPYING
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// When color definition differs for dark and light variant,
|
|
||||||
// it gets @if-ed depending on $variant
|
|
||||||
|
|
||||||
@import '_palette.scss';
|
|
||||||
|
|
||||||
$is_highcontrast:false;
|
|
||||||
|
|
||||||
$_dark_base_color: desaturate($dark_4, 100%);
|
|
||||||
|
|
||||||
$base_color: if($variant == 'light', $light_1, $_dark_base_color);
|
|
||||||
$bg_color: if($variant == 'light', $light_2, lighten($base_color, 5%));
|
|
||||||
$fg_color: if($variant == 'light', transparentize(black, .2), white);
|
|
||||||
|
|
||||||
$selected_fg_color: $light_1;
|
|
||||||
$selected_bg_color: $blue_3;
|
|
||||||
$selected_borders_color: if($variant== 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%));
|
|
||||||
|
|
||||||
$borders_color: if($variant == 'light', transparentize($fg_color, .5), transparentize($fg_color, .9));
|
|
||||||
$outer_borders_color: if($variant == 'light', rgba(255,255,255,0.8), lighten($bg_color, 5%));
|
|
||||||
|
|
||||||
$link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%));
|
|
||||||
$link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%));
|
|
||||||
|
|
||||||
$warning_color: if($variant == 'light', $yellow_5, #cd9309);
|
|
||||||
$error_color: if($variant == 'light', $red_3, $red_4);
|
|
||||||
$success_color: if($variant == 'light', $green_4, $green_5);
|
|
||||||
$destructive_color: $error_color;
|
|
||||||
|
|
||||||
$osd_fg_color: $light_1;
|
|
||||||
$osd_bg_color: $_dark_base_color; //hardcoded for both light & dark
|
|
||||||
$osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5);
|
|
||||||
$osd_insensitive_fg_color: if($variant == 'light', mix($osd_fg_color, $osd_bg_color, 80%), mix($osd_fg_color, $osd_bg_color, 70%));
|
|
||||||
$osd_borders_color: transparentize(black, 0.3);
|
|
||||||
$osd_outer_borders_color: transparentize($osd_fg_color, 0.9);
|
|
||||||
|
|
||||||
$shadow_color: if($variant == 'light', rgba(0,0,0,0.1), rgba(0,0,0,0.2));
|
|
||||||
|
|
||||||
// button
|
|
||||||
$button_mix_factor: 9%;
|
|
||||||
|
|
||||||
// notifications
|
|
||||||
$bubble_buttons_color: if($variant == 'light', darken($bg_color, 7%), lighten($bg_color, 5%));
|
|
||||||
|
|
||||||
// overview background color
|
|
||||||
$system_bg_color: $base_color;
|
|
||||||
|
|
||||||
//insensitive state derived colors
|
|
||||||
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
|
|
||||||
$insensitive_bg_color: mix($bg_color, $base_color, 60%);
|
|
||||||
$insensitive_borders_color: mix($borders_color, $base_color, 60%);
|
|
||||||
|
|
||||||
//colors for the backdrop state, derived from the main colors.
|
|
||||||
$backdrop_base_color: if($variant =='light', darken($base_color,1%), lighten($base_color,1%));
|
|
||||||
$backdrop_bg_color: $bg_color;
|
|
||||||
$backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
|
|
||||||
$backdrop_insensitive_color: if($variant =='light', darken($backdrop_bg_color,15%), lighten($backdrop_bg_color,15%));
|
|
||||||
$backdrop_borders_color: mix($borders_color, $bg_color, 90%);
|
|
||||||
$backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);
|
|
||||||
|
|
||||||
// derived checked colors
|
|
||||||
$checked_bg_color: if($variant=='light', darken($bg_color, 7%), lighten($bg_color, 7%));
|
|
||||||
$checked_fg_color: if($variant=='light', darken($fg_color, 7%), lighten($fg_color, 7%));
|
|
||||||
|
|
||||||
// derived hover colors
|
|
||||||
$hover_bg_color: if($variant=='light', darken($bg_color, 3%), lighten($bg_color, 10%));
|
|
||||||
$hover_fg_color: if($variant=='light', darken($fg_color, 5%), lighten($fg_color, 10%));
|
|
||||||
|
|
||||||
// derived active colors
|
|
||||||
$active_bg_color: if($variant=='light', darken($bg_color, 5%), lighten($bg_color, 12%));
|
|
||||||
$active_fg_color: if($variant=='light', darken($fg_color, 5%), lighten($fg_color, 12%));
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
//This is the RIGHT PLACE to edit the stylesheet
|
|
||||||
|
|
||||||
//let's start by telling people not to edit the generated CSS:
|
|
||||||
$cakeisalie: "This stylesheet is generated, DO NOT EDIT";
|
|
||||||
/* #{$cakeisalie} */
|
|
||||||
|
|
||||||
/* Copyright 2009, 2015 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* Portions adapted from Mx's data/style/default.css
|
|
||||||
* Copyright 2009 Intel Corporation
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU Lesser General Public License,
|
|
||||||
* version 2.1, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Global Values */
|
|
||||||
|
|
||||||
// padding, margin and spacing
|
|
||||||
$base_padding: 6px;
|
|
||||||
$base_margin: 4px;
|
|
||||||
|
|
||||||
// border radii
|
|
||||||
$base_border_radius: 8px;
|
|
||||||
|
|
||||||
// radii of things that display over other things, e.g. popovers
|
|
||||||
$modal_radius: $base_border_radius*2; // 24px
|
|
||||||
|
|
||||||
// Chroma key to flag when a background-color is always occluded, not visible.
|
|
||||||
// This allows any box-shadow behind it to be rendered more efficiently by
|
|
||||||
// omitting the middle rectangle.
|
|
||||||
$invisible_occluded_bg_color: rgba(3,2,1,0);
|
|
||||||
|
|
||||||
// fonts
|
|
||||||
$base_font_size: 11;
|
|
||||||
$text_shadow_color: if($variant == 'light', rgba(255,255,255,0.3), rgba(0,0,0,0.2));
|
|
||||||
|
|
||||||
// icons
|
|
||||||
$base_icon_size: 1.09em;
|
|
||||||
$large_icon_size: $base_icon_size*2; // 32px
|
|
||||||
// $base_icon_size: 16px;
|
|
||||||
|
|
||||||
// Stage
|
|
||||||
stage {
|
|
||||||
@include fontsize($base_font_size);
|
|
||||||
color: $fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Common Stylings */
|
|
||||||
|
|
||||||
// osd panels
|
|
||||||
%osd_panel {
|
|
||||||
color: $osd_fg_color;
|
|
||||||
background-color: $osd_bg_color;
|
|
||||||
border: 1px solid $osd_outer_borders_color;
|
|
||||||
border-radius: 999px;
|
|
||||||
padding: $base_padding*2;
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border: 2px solid $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// icon tiles
|
|
||||||
%tile {
|
|
||||||
border-radius: $base_border_radius * 2; // 16px
|
|
||||||
padding: $base_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
border: 2px solid transparent;
|
|
||||||
transition-duration: 200ms;
|
|
||||||
text-align: center;
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border-color: $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// normal button styling
|
|
||||||
%button {
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 1px;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: $base_padding*.5 $base_padding*4;
|
|
||||||
|
|
||||||
@include button(normal);
|
|
||||||
&:focus { @include button(focus);}
|
|
||||||
&:hover { @include button(hover);}
|
|
||||||
&:insensitive { @include button(insensitive);}
|
|
||||||
&:selected,
|
|
||||||
&:active { @include button(active);}
|
|
||||||
&:checked { @include button(checked);}
|
|
||||||
|
|
||||||
&.flat {
|
|
||||||
@include button(normal, $flat:true);
|
|
||||||
&:focus { @include button(focus, $flat:true);}
|
|
||||||
&:hover { @include button(hover, $flat:true);}
|
|
||||||
&:insensitive { @include button(insensitive, $flat:true);}
|
|
||||||
&:selected,
|
|
||||||
&:active { @include button(active, $flat:true);}
|
|
||||||
&:checked { @include button(checked, $flat:true);}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// normal entry style
|
|
||||||
%entry {
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
padding: $base_padding*1.5 $base_padding*1.5;
|
|
||||||
color: $fg_color;
|
|
||||||
selection-background-color: $selected_bg_color;
|
|
||||||
selected-color: $selected_fg_color;
|
|
||||||
|
|
||||||
@include entry(normal);
|
|
||||||
&:hover { @include entry(hover);}
|
|
||||||
&:focus { @include entry(focus);}
|
|
||||||
&:insensitive { @include entry(insensitive);}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// buttons in dialogs/notifications
|
|
||||||
// lighter in color and have a greater radius
|
|
||||||
%bubble_button {
|
|
||||||
padding: $base_padding * 2;
|
|
||||||
font-weight: bold !important;
|
|
||||||
|
|
||||||
&:ltr {margin-right: 1px;}
|
|
||||||
&:rtl {margin-left: 1px;}
|
|
||||||
|
|
||||||
@include button(normal, $c:$bubble_buttons_color);
|
|
||||||
&:insensitive { @include button(insensitive, $c:$bubble_buttons_color);}
|
|
||||||
&:focus { @include button(focus, $c:$bubble_buttons_color);}
|
|
||||||
&:hover { @include button(hover, $c:$bubble_buttons_color);}
|
|
||||||
&:active { @include button(active, $c:$bubble_buttons_color);}
|
|
||||||
&:checked { @include button(checked, $c:$bubble_buttons_color);}
|
|
||||||
|
|
||||||
&:first-child:ltr {
|
|
||||||
border-radius: 0 0 0 $modal_radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child:ltr {
|
|
||||||
border-radius: 0 0 $modal_radius;
|
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child:rtl {
|
|
||||||
border-radius: 0 0 $modal_radius;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child:rtl {
|
|
||||||
border-radius: 0 0 0 $modal_radius;
|
|
||||||
margin-left: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child:last-child {
|
|
||||||
border-radius: 0 0 $modal_radius $modal_radius;
|
|
||||||
margin-left: 0 !important;
|
|
||||||
margin-right: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// buttons on OSD elements
|
|
||||||
// that are undecorated by default and use OSD colors
|
|
||||||
%osd_button {
|
|
||||||
@include button(undecorated);
|
|
||||||
&:insensitive { @include button(undecorated, $tc:$osd_fg_color, $c:$osd_bg_color);}
|
|
||||||
&:focus { @include button(focus, $tc:$osd_fg_color, $c:$osd_bg_color);}
|
|
||||||
&:hover { @include button(hover, $tc:$osd_fg_color, $c:$osd_bg_color);}
|
|
||||||
&:active { @include button(active, $tc:$osd_fg_color, $c:$osd_bg_color);}
|
|
||||||
&:outlined,&:checked { @include button(checked, $tc:$osd_fg_color, $c:$osd_bg_color);}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// tooltip
|
|
||||||
%tooltip {
|
|
||||||
background-color: $osd_bg_color;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
border:1px solid $osd_outer_borders_color;
|
|
||||||
border-radius: 99px;
|
|
||||||
padding: $base_padding $base_padding * 2;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
background-color: $osd_bg_color;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
border: 1px solid $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* General Typography */
|
|
||||||
|
|
||||||
%large_title {
|
|
||||||
font-weight: 300;
|
|
||||||
@include fontsize(24);
|
|
||||||
}
|
|
||||||
|
|
||||||
%title_1 {
|
|
||||||
font-weight: 800;
|
|
||||||
@include fontsize(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
%title_2 {
|
|
||||||
font-weight: 800;
|
|
||||||
@include fontsize(15);
|
|
||||||
}
|
|
||||||
|
|
||||||
%title_3 {
|
|
||||||
font-weight: 700;
|
|
||||||
@include fontsize(15);
|
|
||||||
}
|
|
||||||
|
|
||||||
%title_4 {
|
|
||||||
font-weight: 700;
|
|
||||||
@include fontsize(13);
|
|
||||||
}
|
|
||||||
|
|
||||||
%heading {
|
|
||||||
font-weight: 700;
|
|
||||||
@include fontsize(11);
|
|
||||||
}
|
|
||||||
|
|
||||||
%caption_heading {
|
|
||||||
font-weight: 700;
|
|
||||||
@include fontsize(9);
|
|
||||||
}
|
|
||||||
|
|
||||||
%caption {
|
|
||||||
font-weight: 400;
|
|
||||||
@include fontsize(9);
|
|
||||||
}
|
|
||||||
|
|
||||||
%smaller {
|
|
||||||
font-weight: 400;
|
|
||||||
@include fontsize(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
%monospace {font-family: monospace;}
|
|
||||||
%numeric { font-feature-settings: "tnum";}
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
// Drawing mixins
|
|
||||||
|
|
||||||
// generic drawing of more complex things
|
|
||||||
|
|
||||||
@function draw_widget_edge($c:$outer_borders_color) {
|
|
||||||
// outer highlight "used" on most widgets
|
|
||||||
@return 0 1px $c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// provide font size in rem, with px fallback
|
|
||||||
@mixin fontsize($size: 24, $base: 16) {
|
|
||||||
font-size: round($size) + pt;
|
|
||||||
//font-size: ($size / $base) * 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@mixin draw_shadows($shadow1, $shadow2:none, $shadow3:none, $shadow4:none) {
|
|
||||||
//
|
|
||||||
// Helper function to stack up to 4 box-shadows;
|
|
||||||
//
|
|
||||||
@if $shadow4!=none { box-shadow: $shadow1, $shadow2, $shadow3, $shadow4; }
|
|
||||||
@else if $shadow3!=none { box-shadow: $shadow1, $shadow2, $shadow3; }
|
|
||||||
@else if $shadow2!=none { box-shadow: $shadow1, $shadow2; }
|
|
||||||
@else { box-shadow: $shadow1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// entries
|
|
||||||
|
|
||||||
@mixin entry($t, $fc:$selected_bg_color) {
|
|
||||||
//
|
|
||||||
// Entries drawing function
|
|
||||||
//
|
|
||||||
// $t: entry type
|
|
||||||
// $fc: focus color
|
|
||||||
//
|
|
||||||
// possible $t values:
|
|
||||||
// normal, focus, insensitive
|
|
||||||
//
|
|
||||||
transition-duration: 100ms;
|
|
||||||
|
|
||||||
@if $t==normal {
|
|
||||||
background-color: transparentize($fg_color, 0.9);
|
|
||||||
color: transparentize($fg_color,0.3);
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow: inset 0 0 0 1px $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $t==focus {
|
|
||||||
background-color: mix(transparentize($fg_color, 0.8), $selected_bg_color, 95%);
|
|
||||||
box-shadow: inset 0 0 0 2px $fc;
|
|
||||||
color: $fg_color;
|
|
||||||
&:hover {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $t==hover {
|
|
||||||
background-color:transparentize($fg_color, 0.8);
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $t==insensitive {
|
|
||||||
background-color:transparentize($insensitive_fg_color, 0.8);
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// On-screen Keyboard
|
|
||||||
@mixin keyboard_key($t, $c:$osd_bg_color, $tc:$osd_fg_color) {
|
|
||||||
//
|
|
||||||
// Keyboard key drawing function
|
|
||||||
//
|
|
||||||
// $t: key type,
|
|
||||||
// $c: base key color for colored* types
|
|
||||||
// $tc: optional text color for colored* types
|
|
||||||
//
|
|
||||||
// possible $t values:
|
|
||||||
// normal, hover, active, insensitive, insensitive-active,
|
|
||||||
// backdrop, backdrop-active, backdrop-insensitive, backdrop-insensitive-active,
|
|
||||||
// osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
|
|
||||||
//
|
|
||||||
|
|
||||||
// normal key
|
|
||||||
@if $t==normal {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($c, 3%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// focused key
|
|
||||||
@if $t==focus {
|
|
||||||
color: $tc;
|
|
||||||
background-color: mix(lighten($c, 3%), $selected_bg_color, 90%);
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.4);
|
|
||||||
&:hover {
|
|
||||||
background-color: mix(lighten($c, 8%), $selected_bg_color, 90%);
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.3);
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: mix(lighten($c, 10%), $selected_bg_color, 90%);
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// hover key
|
|
||||||
@else if $t==hover {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($c, 7%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// active key
|
|
||||||
@else if $t==active {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($c, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// checked key
|
|
||||||
@else if $t==checked {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($c, 15%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// insensitive key
|
|
||||||
@else if $t==insensitive {
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
background-color: $insensitive_bg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset
|
|
||||||
@else if $t==undecorated {
|
|
||||||
background-color: transparent;
|
|
||||||
background-image: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Button drawing function
|
|
||||||
//
|
|
||||||
// $t: button type,
|
|
||||||
// $c: base button colors, derived from fg_color
|
|
||||||
// $tc: base button colors, derived from fg_color
|
|
||||||
//
|
|
||||||
// possible $t values:
|
|
||||||
// normal, hover, active, insensitive, insensitive-active,
|
|
||||||
// backdrop, backdrop-active, backdrop-insensitive, backdrop-insensitive-active,
|
|
||||||
// osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
|
|
||||||
//
|
|
||||||
// since buttons are all flat an borderless now the mixin is simpler
|
|
||||||
|
|
||||||
@mixin button($t, $tc:$fg_color, $c:$bg_color, $flat: false) {
|
|
||||||
|
|
||||||
$button_bg_color: mix($tc, $c, $button_mix_factor);
|
|
||||||
transition-duration: 100ms;
|
|
||||||
|
|
||||||
// normal button
|
|
||||||
@if $t==normal {
|
|
||||||
color: $tc;
|
|
||||||
background-color: $button_bg_color;
|
|
||||||
@if $flat {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow: inset 0 0 0 1px $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// hover button
|
|
||||||
@else if $t==hover {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($button_bg_color, 3%);
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow: inset 0 0 0 1px $hc_inset_color !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// active button
|
|
||||||
@else if $t==active {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($button_bg_color, 9%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// checked button
|
|
||||||
@else if $t==checked {
|
|
||||||
color: $tc;
|
|
||||||
background-color: lighten($button_bg_color, 9%);
|
|
||||||
&:hover { background-color: lighten($button_bg_color, 12%);}
|
|
||||||
&:active { background-color: lighten($button_bg_color, 15%);}
|
|
||||||
}
|
|
||||||
|
|
||||||
// focused button
|
|
||||||
@if $t==focus {
|
|
||||||
color: $tc;
|
|
||||||
background-color: mix($button_bg_color, $selected_bg_color, 90%);
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.4) !important;
|
|
||||||
&:hover {
|
|
||||||
background-color: mix(lighten($button_bg_color, 3%), $selected_bg_color, 90%);
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.3) !important;
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: mix(lighten($button_bg_color, 6%), $selected_bg_color, 90%);
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_bg_color, 0.3) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// insensitive button
|
|
||||||
@else if $t==insensitive {
|
|
||||||
color: transparentize($tc, 0.5);
|
|
||||||
background-color: transparentize($tc, .95);
|
|
||||||
}
|
|
||||||
|
|
||||||
// default/suggested button
|
|
||||||
@else if $t==default {
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
color: $selected_fg_color;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
box-shadow: inset 0 0 0 2px transparentize($selected_fg_color, .4) !important;
|
|
||||||
}
|
|
||||||
&:hover, &:focus {
|
|
||||||
background-color: lighten($selected_bg_color, 5%);
|
|
||||||
color: lighten($selected_fg_color, 5%);
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background-color: darken($selected_bg_color, 7%);
|
|
||||||
color: darken($selected_fg_color, 7%);
|
|
||||||
}
|
|
||||||
&:insensitive {
|
|
||||||
@include button(insensitive);
|
|
||||||
background-color: transparentize($selected_bg_color, .5);
|
|
||||||
color: transparentize($selected_fg_color, .5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset
|
|
||||||
@else if $t==undecorated {
|
|
||||||
background-color: transparent;
|
|
||||||
background-color: none;
|
|
||||||
box-shadow: none;
|
|
||||||
&:insensitive {
|
|
||||||
@include button(insensitive);
|
|
||||||
background-color: transparent;
|
|
||||||
color: transparentize($selected_fg_color, .5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tile
|
|
||||||
@mixin tile_button($color, $flat: true) {
|
|
||||||
@extend %tile;
|
|
||||||
@if $flat {
|
|
||||||
background-color: transparent;
|
|
||||||
} @else {
|
|
||||||
background-color: transparentize($color, .84);
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow: inset 999px 0 0 0 transparentize($color, .2); // bit of a hack
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover { background-color: transparentize($color, .9);}
|
|
||||||
&:selected, &:focus {
|
|
||||||
background-color: transparentize($color, .87);
|
|
||||||
&:hover { background-color: transparentize($color, .84);}
|
|
||||||
&:active { background-color: transparentize($color, .87);}
|
|
||||||
}
|
|
||||||
&:active { background-color: transparentize($color, .84);}
|
|
||||||
&:outlined, &:checked {
|
|
||||||
background-color: transparentize($color, .81);
|
|
||||||
&:active { background-color: transparentize($color, .78);}
|
|
||||||
&:hover { background-color: transparentize($color, .75);}
|
|
||||||
}
|
|
||||||
&:drop {
|
|
||||||
border: 2px solid transparentize($selected_bg_color, .2); //already 2px transparent so no jumping
|
|
||||||
background-color: transparentize($selected_bg_color, .8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// overview icon, dash, app grid
|
|
||||||
@mixin overview_icon($color, $flat: true) {
|
|
||||||
transition-duration: 400ms;
|
|
||||||
.overview-icon {
|
|
||||||
@extend %tile;
|
|
||||||
}
|
|
||||||
@if $flat {
|
|
||||||
.overview-icon { background-color: transparent;}
|
|
||||||
} @else {
|
|
||||||
.overview-icon {
|
|
||||||
background-color: transparentize($color, .93);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover .overview-icon { background-color: transparentize($color, .9);}
|
|
||||||
|
|
||||||
&:selected .overview-icon,
|
|
||||||
&:focus .overview-icon {
|
|
||||||
background-color: transparentize($color, .87);
|
|
||||||
&:hover .overview-icon { background-color: transparentize($color, .84);}
|
|
||||||
&:active .overview-icon { background-color: transparentize($color, .87);}
|
|
||||||
}
|
|
||||||
&:active .overview-icon { background-color: transparentize($color, .84);}
|
|
||||||
&:outlined .overview-icon,
|
|
||||||
&:checked .overview-icon {
|
|
||||||
background-color: transparentize($color, .81);
|
|
||||||
&:active .overview-icon { background-color: transparentize($color, .78);}
|
|
||||||
&:hover .overview-icon { background-color: transparentize($color, .75);}
|
|
||||||
}
|
|
||||||
&:drop .overview-icon {
|
|
||||||
border: 2px solid transparentize($selected_bg_color, .2); //already 2px transparent so no jumping
|
|
||||||
background-color: transparentize($selected_bg_color, .8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// styling for elements within popovers that look like notifications
|
|
||||||
@mixin card($flat: false) {
|
|
||||||
border-radius: $base_border_radius*1.5;
|
|
||||||
margin: $base_margin;
|
|
||||||
|
|
||||||
@if $flat {
|
|
||||||
@include button(undecorated);
|
|
||||||
box-shadow: none !important;
|
|
||||||
} @else {
|
|
||||||
@include button(normal);
|
|
||||||
}
|
|
||||||
&:hover {@include button(hover);}
|
|
||||||
&:active {@include button(active);}
|
|
||||||
&:focus {@include button(focus);}
|
|
||||||
}
|
|
||||||
|
|
||||||
// styling for all menuitems in popovers
|
|
||||||
@mixin menuitem($bg, $flat: true) {
|
|
||||||
|
|
||||||
// lighten the background color always
|
|
||||||
$bg: lighten($bg,5%);
|
|
||||||
|
|
||||||
font-weight: normal;
|
|
||||||
spacing: $base_padding;
|
|
||||||
transition-duration: 100ms;
|
|
||||||
padding: $base_padding*1.5 $base_padding*2;
|
|
||||||
|
|
||||||
&:ltr {padding-left: $base_padding;}
|
|
||||||
&:rtl {padding-right: $base_padding;}
|
|
||||||
|
|
||||||
@if $flat {
|
|
||||||
@include button(undecorated);
|
|
||||||
box-shadow: none !important;
|
|
||||||
} @else {
|
|
||||||
@include button(normal, $c:$bg);
|
|
||||||
}
|
|
||||||
&:focus,
|
|
||||||
&:hover {
|
|
||||||
@include button(hover, $c:$bg);
|
|
||||||
}
|
|
||||||
&:active {@include button(active, $c:$bg);}
|
|
||||||
&:checked {@include button(checked, $c:$bg);}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// When color definition differs for dark and light variant,
|
|
||||||
// it gets @if ed depending on $variant
|
|
||||||
|
|
||||||
@import '_palette.scss';
|
|
||||||
|
|
||||||
$is_highcontrast:true;
|
|
||||||
|
|
||||||
$base_color: if($variant == 'light', white, black);
|
|
||||||
$bg_color: if($variant == 'light', darken($base_color, 10%), lighten($base_color, 10%));
|
|
||||||
$fg_color: if($variant == 'light', transparentize(black, .2), white);
|
|
||||||
|
|
||||||
$selected_fg_color: white;
|
|
||||||
$selected_bg_color: $blue_3;
|
|
||||||
|
|
||||||
$selected_borders_color: darken($selected_bg_color, 20%);
|
|
||||||
$borders_color: if($variant == 'light', transparentize($fg_color, .5), transparentize($fg_color, .7));
|
|
||||||
$outer_borders_color: $borders_color;
|
|
||||||
$link_color: lighten($selected_bg_color,20%);
|
|
||||||
$link_visited_color: lighten($selected_bg_color,10%);
|
|
||||||
|
|
||||||
$warning_color: if($variant == 'light', $yellow_5, #cd9309);
|
|
||||||
$error_color: if($variant == 'light', $red_3, $red_4);
|
|
||||||
$success_color: if($variant == 'light', $green_4, $green_5);
|
|
||||||
$destructive_color: $error_color;
|
|
||||||
|
|
||||||
$osd_fg_color: white;
|
|
||||||
$osd_bg_color: $base_color;
|
|
||||||
$osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5);
|
|
||||||
$osd_insensitive_fg_color: if($variant == 'light', mix($osd_fg_color, $osd_bg_color, 80%), mix($osd_fg_color, $osd_bg_color, 70%));
|
|
||||||
$osd_borders_color: transparentize($osd_fg_color, 0.8);
|
|
||||||
$osd_outer_borders_color: $osd_borders_color;
|
|
||||||
|
|
||||||
$shadow_color: rgba(0,0,0,0);
|
|
||||||
|
|
||||||
// hc
|
|
||||||
$hc_inset_color: transparentize($fg_color, 0.7);
|
|
||||||
|
|
||||||
// button
|
|
||||||
$button_mix_factor: 20%;
|
|
||||||
|
|
||||||
// notifications
|
|
||||||
$bubble_buttons_color: if($variant == 'light', darken($bg_color, 7%), lighten($bg_color, 5%));
|
|
||||||
|
|
||||||
// overview background color
|
|
||||||
$system_bg_color: black;
|
|
||||||
|
|
||||||
//insensitive state derived colors
|
|
||||||
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
|
|
||||||
$insensitive_bg_color: mix($bg_color, $base_color, 60%);
|
|
||||||
$insensitive_borders_color: $borders_color;
|
|
||||||
|
|
||||||
//colors for the backdrop state, derived from the main colors.
|
|
||||||
$backdrop_base_color: lighten($base_color,1%);
|
|
||||||
$backdrop_bg_color: $bg_color;
|
|
||||||
$backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
|
|
||||||
$backdrop_insensitive_color: lighten($backdrop_bg_color,15%);
|
|
||||||
$backdrop_borders_color: mix($borders_color, $bg_color, 90%);
|
|
||||||
$backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);
|
|
||||||
|
|
||||||
// derived checked colors
|
|
||||||
$checked_bg_color: if($variant=='light', darken($bg_color, 12%), lighten($bg_color, 18%));
|
|
||||||
$checked_fg_color: if($variant=='light', darken($fg_color, 12%), lighten($fg_color, 18%));
|
|
||||||
|
|
||||||
// derived hover colors
|
|
||||||
$hover_bg_color: if($variant=='light', darken($bg_color, 8%), lighten($bg_color, 20%));
|
|
||||||
$hover_fg_color: if($variant=='light', darken($fg_color, 10%), lighten($fg_color, 20%));
|
|
||||||
|
|
||||||
// derived active colors
|
|
||||||
$active_bg_color: if($variant=='light', darken($bg_color, 10%), lighten($bg_color, 22%));
|
|
||||||
$active_fg_color: if($variant=='light', darken($fg_color, 10%), lighten($fg_color, 22%));
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
//GNOME Color Palette
|
|
||||||
$blue_1: #99c1f1;
|
|
||||||
$blue_2: #62a0ea;
|
|
||||||
$blue_3: #3584e4;
|
|
||||||
$blue_4: #1c71d8;
|
|
||||||
$blue_5: #1a5fb4;
|
|
||||||
$green_1: #8ff0a4;
|
|
||||||
$green_2: #57e389;
|
|
||||||
$green_3: #33d17a;
|
|
||||||
$green_4: #2ec27e;
|
|
||||||
$green_5: #26a269;
|
|
||||||
$yellow_1: #f9f06b;
|
|
||||||
$yellow_2: #f8e45c;
|
|
||||||
$yellow_3: #f6d32d;
|
|
||||||
$yellow_4: #f5c211;
|
|
||||||
$yellow_5: #e5a50a;
|
|
||||||
$orange_1: #ffbe6f;
|
|
||||||
$orange_2: #ffa348;
|
|
||||||
$orange_3: #ff7800;
|
|
||||||
$orange_4: #e66100;
|
|
||||||
$orange_5: #c64600;
|
|
||||||
$red_1: #f66151;
|
|
||||||
$red_2: #ed333b;
|
|
||||||
$red_3: #e01b24;
|
|
||||||
$red_4: #c01c28;
|
|
||||||
$red_5: #a51d2d;
|
|
||||||
$purple_1: #dc8add;
|
|
||||||
$purple_2: #c061cb;
|
|
||||||
$purple_3: #9141ac;
|
|
||||||
$purple_4: #813d9c;
|
|
||||||
$purple_5: #613583;
|
|
||||||
$brown_1: #cdab8f;
|
|
||||||
$brown_2: #b5835a;
|
|
||||||
$brown_3: #986a44;
|
|
||||||
$brown_4: #865e3c;
|
|
||||||
$brown_5: #63452c;
|
|
||||||
$light_1: #ffffff;
|
|
||||||
$light_2: #f6f5f4;
|
|
||||||
$light_3: #deddda;
|
|
||||||
$light_4: #c0bfbc;
|
|
||||||
$light_5: #9a9996;
|
|
||||||
$dark_1: #77767b;
|
|
||||||
$dark_2: #5e5c64;
|
|
||||||
$dark_3: #3d3846;
|
|
||||||
$dark_4: #241f31;
|
|
||||||
$dark_5: #000000;
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
//
|
|
||||||
// Shell widgets stylesheets are placed in separate .scss files
|
|
||||||
// in 'widgets' and imported into the main stylesheet in this file.
|
|
||||||
// To create or update a widget for the shell modify the list below.
|
|
||||||
//
|
|
||||||
|
|
||||||
/* WIDGETS */
|
|
||||||
|
|
||||||
// Primary widgets
|
|
||||||
@import 'widgets/base';
|
|
||||||
@import 'widgets/entries';
|
|
||||||
@import 'widgets/buttons';
|
|
||||||
@import 'widgets/check-box';
|
|
||||||
@import 'widgets/switches';
|
|
||||||
@import 'widgets/slider';
|
|
||||||
@import 'widgets/scrollbars';
|
|
||||||
// Popovers
|
|
||||||
@import 'widgets/popovers';
|
|
||||||
@import 'widgets/calendar';
|
|
||||||
@import 'widgets/message-list';
|
|
||||||
@import 'widgets/ibus-popup';
|
|
||||||
// Notifications
|
|
||||||
@import 'widgets/notifications';
|
|
||||||
@import 'widgets/hotplug';
|
|
||||||
// Dialogs
|
|
||||||
@import 'widgets/dialogs';
|
|
||||||
// OSDs
|
|
||||||
@import 'widgets/osd';
|
|
||||||
@import 'widgets/switcher-popup';
|
|
||||||
@import 'widgets/workspace-switcher';
|
|
||||||
@import 'widgets/screenshot';
|
|
||||||
// Panel
|
|
||||||
@import 'widgets/panel';
|
|
||||||
@import 'widgets/corner-ripple';
|
|
||||||
@import 'widgets/quick-settings';
|
|
||||||
// Overview
|
|
||||||
@import 'widgets/overview';
|
|
||||||
@import 'widgets/window-picker';
|
|
||||||
@import 'widgets/search-entry';
|
|
||||||
@import 'widgets/search-results';
|
|
||||||
@import 'widgets/dash';
|
|
||||||
@import 'widgets/app-grid';
|
|
||||||
@import 'widgets/workspace-thumbnails';
|
|
||||||
// A11y / misc
|
|
||||||
@import 'widgets/a11y';
|
|
||||||
@import 'widgets/misc';
|
|
||||||
@import 'widgets/keyboard';
|
|
||||||
@import 'widgets/looking-glass';
|
|
||||||
// Lock / login screen
|
|
||||||
@import 'widgets/login-lock';
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
|
||||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
|
||||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
|
||||||
xmlns="http://usefulinc.com/ns/doap#">
|
|
||||||
|
|
||||||
<name xml:lang="en">GNOME Shell Sass</name>
|
|
||||||
<shortdesc xml:lang="en">Sass sources of GNOME Shell</shortdesc>
|
|
||||||
<description>GNOME Shell Sass is a project intended to allow the sharing of the
|
|
||||||
sass theme sources between gnome-shell and other projects like gnome-shell-extensions.</description>
|
|
||||||
|
|
||||||
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
|
|
||||||
<programming-language>sass</programming-language>
|
|
||||||
<programming-language>css</programming-language>
|
|
||||||
|
|
||||||
<maintainer>
|
|
||||||
<foaf:Person>
|
|
||||||
<foaf:name>Carlos Soriano</foaf:name>
|
|
||||||
<foaf:mbox rdf:resource="mailto:csoriano@gnome.org" />
|
|
||||||
<gnome:userid>csoriano</gnome:userid>
|
|
||||||
</foaf:Person>
|
|
||||||
</maintainer>
|
|
||||||
<maintainer>
|
|
||||||
<foaf:Person>
|
|
||||||
<foaf:name>Florian Müllner</foaf:name>
|
|
||||||
<foaf:mbox rdf:resource="mailto:fmuellner@gnome.org" />
|
|
||||||
<gnome:userid>fmuellner</gnome:userid>
|
|
||||||
</foaf:Person>
|
|
||||||
</maintainer>
|
|
||||||
<maintainer>
|
|
||||||
<foaf:Person>
|
|
||||||
<foaf:name>Jakub Steiner</foaf:name>
|
|
||||||
<foaf:mbox rdf:resource="mailto:jimmac@gmail.com" />
|
|
||||||
<gnome:userid>jimmac</gnome:userid>
|
|
||||||
</foaf:Person>
|
|
||||||
</maintainer>
|
|
||||||
</Project>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
// Pointer location
|
|
||||||
.ripple-pointer-location {
|
|
||||||
width: $ripple_size;
|
|
||||||
height: $ripple_size;
|
|
||||||
border-radius: $ripple_size * 0.5; // radius equals the size of the box to give us the curve
|
|
||||||
background-color: lighten(transparentize($selected_bg_color, 0.7), 30%);
|
|
||||||
box-shadow: 0 0 2px 2px lighten($selected_bg_color, 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointer accessibility notifications
|
|
||||||
.pie-timer {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
-pie-border-width: 3px;
|
|
||||||
-pie-border-color: $selected_bg_color;
|
|
||||||
-pie-background-color: lighten(transparentize($selected_bg_color, 0.7), 40%);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Screen zoom/Magnifier
|
|
||||||
.magnifier-zoom-region {
|
|
||||||
border: 2px solid $selected_bg_color;
|
|
||||||
|
|
||||||
&.full-screen { border-width: 0; }
|
|
||||||
}
|
|
||||||
@@ -1,177 +0,0 @@
|
|||||||
/* App Grid */
|
|
||||||
|
|
||||||
$app_icon_size: 96px;
|
|
||||||
|
|
||||||
// app icons
|
|
||||||
.icon-grid {
|
|
||||||
row-spacing: $base_padding * 2;
|
|
||||||
column-spacing: $base_padding * 2;
|
|
||||||
max-row-spacing: $base_padding * 7;
|
|
||||||
max-column-spacing: $base_padding * 7;
|
|
||||||
page-padding-top: $base_padding * 4;
|
|
||||||
page-padding-bottom: $base_padding * 4;
|
|
||||||
page-padding-left: $base_padding * 3;
|
|
||||||
page-padding-right: $base_padding * 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* App Icons */
|
|
||||||
|
|
||||||
// Icon tiles in the app grid
|
|
||||||
.app-well-app {
|
|
||||||
@include overview_icon($osd_fg_color);
|
|
||||||
|
|
||||||
.overview-icon {
|
|
||||||
padding: $base_padding*2;
|
|
||||||
border-radius: $base_border_radius*3;
|
|
||||||
}
|
|
||||||
.overview-icon.overview-icon-with-label {
|
|
||||||
> StBoxLayout {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// app folders
|
|
||||||
.app-well-app.app-folder {
|
|
||||||
@include overview_icon($fg_color, $flat: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// expanded folder
|
|
||||||
.app-folder-dialog {
|
|
||||||
border-radius: $modal_radius*4;
|
|
||||||
background-color: $bg_color;
|
|
||||||
padding: $base_padding*2;
|
|
||||||
box-shadow:inset 0 0 0 1px $outer_borders_color;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow:inset 0 0 0 2px $hc_inset_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .folder-name-container {
|
|
||||||
padding: 24px 36px 0;
|
|
||||||
spacing: 12px;
|
|
||||||
|
|
||||||
& .folder-name-label,
|
|
||||||
& .folder-name-entry {
|
|
||||||
@extend %title_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .folder-name-entry {
|
|
||||||
width: 12em;
|
|
||||||
border-radius: $base_border_radius*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: this is to keep the label in sync with the entry */
|
|
||||||
& .folder-name-label { padding: 5px 7px; color: $osd_fg_color; }
|
|
||||||
|
|
||||||
& .edit-folder-button {
|
|
||||||
@extend %button;
|
|
||||||
padding: 0;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 99px;
|
|
||||||
& > StIcon { icon-size: $base_icon_size }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .icon-grid {
|
|
||||||
row-spacing: $base_padding * 2;
|
|
||||||
column-spacing: $base_padding * 5;
|
|
||||||
page-padding-top: 0;
|
|
||||||
page-padding-bottom: 0;
|
|
||||||
page-padding-left: 0;
|
|
||||||
page-padding-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .page-indicators {
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-folder-dialog-container {
|
|
||||||
padding: $base_padding*2;
|
|
||||||
width: 720px;
|
|
||||||
height: 720px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Running app indicator (also shown in dash)
|
|
||||||
.app-well-app-running-dot {
|
|
||||||
height: 5px;
|
|
||||||
width: 5px;
|
|
||||||
border-radius:5px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
background-color: $osd_fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename popup for app folders
|
|
||||||
.rename-folder-popup {
|
|
||||||
.rename-folder-popup-item {
|
|
||||||
spacing: $base_padding;
|
|
||||||
&:ltr, &:rtl { padding: 0 $base_padding * 2; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// App Grid pagination indicators
|
|
||||||
.page-indicator {
|
|
||||||
padding: $base_padding $base_padding * 2 0;
|
|
||||||
transition-duration:400ms;
|
|
||||||
|
|
||||||
.page-indicator-icon {
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
border-radius: 10px; // the same as height&width
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.apps-scroll-view {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shutdown and other actions in the grid
|
|
||||||
.system-action-icon {
|
|
||||||
background-color: rgba(0,0,0,0.8);
|
|
||||||
color: white;
|
|
||||||
border-radius: 99px;
|
|
||||||
icon-size: $app_icon_size * 0.5;
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow: inset 0 0 0 2px $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-navigation-hint {
|
|
||||||
&.dnd {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.next:ltr,
|
|
||||||
&.previous:rtl {
|
|
||||||
background-gradient-start: rgba(255, 255, 255, 0.05);
|
|
||||||
background-gradient-end: transparent;
|
|
||||||
background-gradient-direction: horizontal;
|
|
||||||
border-radius: $modal_radius*1.5 0px 0px $modal_radius*1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.previous:ltr,
|
|
||||||
&.next:rtl {
|
|
||||||
background-gradient-start: transparent;
|
|
||||||
background-gradient-end: rgba(255, 255, 255, 0.05);
|
|
||||||
background-gradient-direction: horizontal;
|
|
||||||
border-radius: 0px $modal_radius*1.5 $modal_radius*1.5 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-navigation-arrow {
|
|
||||||
margin: 6px;
|
|
||||||
padding: 18px;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
border-radius: 99px;
|
|
||||||
@if $is_highcontrast {
|
|
||||||
@include button(normal, $osd_fg_color, transparentize($osd_bg_color, 0.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
&:insensitive { @include button(undecorated, $osd_fg_color, transparentize($osd_bg_color, 0.5));}
|
|
||||||
&:hover { @include button(hover, $osd_fg_color, transparentize($osd_bg_color, 0.5));}
|
|
||||||
&:active { @include button(active, $osd_fg_color, transparentize($osd_bg_color, 0.5));}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Links
|
|
||||||
.shell-link {
|
|
||||||
color: $link_color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: lighten($link_color, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outline for low res icons
|
|
||||||
.lowres-icon {
|
|
||||||
icon-shadow: 0 1px 2px rgba(black, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dropshadow for large icons
|
|
||||||
.icon-dropshadow {
|
|
||||||
icon-shadow: 0 1px 5px rgba(black, 0.8);
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/* Buttons */
|
|
||||||
|
|
||||||
.button {
|
|
||||||
@extend %button; // that's it
|
|
||||||
min-height: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-button {
|
|
||||||
@extend .button; // same style as buttons
|
|
||||||
|
|
||||||
border-radius: 99px;
|
|
||||||
padding: $base_padding*2;
|
|
||||||
min-height: 16px;
|
|
||||||
|
|
||||||
StIcon {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
-st-icon-style: symbolic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
/* Date/Time Menu */
|
|
||||||
|
|
||||||
// overall menu
|
|
||||||
#calendarArea {
|
|
||||||
padding: $base_padding - 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calendar menu side column
|
|
||||||
.datemenu-calendar-column {
|
|
||||||
spacing: $base_padding;
|
|
||||||
&:ltr {padding-left: $base_padding;}
|
|
||||||
&:rtl {padding-right: $base_padding;}
|
|
||||||
.datemenu-displays-box {spacing: $base_padding;}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* today button (the date) */
|
|
||||||
.datemenu-today-button {
|
|
||||||
@include card(flat);
|
|
||||||
padding: $base_padding * 1.5;
|
|
||||||
|
|
||||||
// weekday label
|
|
||||||
.day-label {
|
|
||||||
@extend %heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
// date label
|
|
||||||
.date-label {
|
|
||||||
@extend %title_2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calendar */
|
|
||||||
.calendar {
|
|
||||||
@include card(flat);
|
|
||||||
margin-top: 0;
|
|
||||||
|
|
||||||
// month header
|
|
||||||
.calendar-month-header {
|
|
||||||
|
|
||||||
// prev/next month icons
|
|
||||||
.calendar-change-month-back StIcon,
|
|
||||||
.calendar-change-month-forward StIcon {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// month label
|
|
||||||
.calendar-month-label {
|
|
||||||
@extend %heading;
|
|
||||||
padding: 8px 0;
|
|
||||||
}
|
|
||||||
.pager-button {
|
|
||||||
background-color: transparent;
|
|
||||||
height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
margin: 2px;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
&:hover, &:focus {background-color: $hover_bg_color;}
|
|
||||||
&:active {background-color: $active_bg_color;}
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border:1px solid $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$calendar_day_size: 3em;
|
|
||||||
|
|
||||||
.calendar-day-base {
|
|
||||||
text-align: center;
|
|
||||||
margin: 2px;
|
|
||||||
padding: 0 !important;
|
|
||||||
height: $calendar_day_size !important;
|
|
||||||
width: $calendar_day_size !important;
|
|
||||||
border-radius: 99px;
|
|
||||||
transition-duration: 100ms;
|
|
||||||
@extend %numeric;
|
|
||||||
@extend %smaller;
|
|
||||||
|
|
||||||
&:hover {background-color: $hover_bg_color;}
|
|
||||||
&:focus {
|
|
||||||
background-color: mix($bg_color, $selected_bg_color, 80%);
|
|
||||||
color: $selected_fg_color;
|
|
||||||
box-shadow:inset 0 0 0 2px transparentize($selected_bg_color, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,&:selected {
|
|
||||||
color: $active_fg_color;
|
|
||||||
background-color: $active_bg_color;
|
|
||||||
&:focus {
|
|
||||||
background-color: mix($active_bg_color, $selected_bg_color, 80%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// day of week heading
|
|
||||||
&.calendar-day-heading {
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
padding-top: $base_padding;
|
|
||||||
height: 16px !important; // force heading to be smaller height
|
|
||||||
font-weight: 600;
|
|
||||||
@extend %smaller;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-day {
|
|
||||||
font-weight: 600;
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border:1px solid $hc_inset_color;
|
|
||||||
border-radius: 9px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.calendar-work-day {}
|
|
||||||
.calendar-nonwork-day {color: $insensitive_fg_color;}
|
|
||||||
.calendar-other-month-day {
|
|
||||||
color: transparentize($fg_color, 0.5);
|
|
||||||
&.calendar-nonwork-day {
|
|
||||||
color: transparentize($insensitive_fg_color, 0.5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Today
|
|
||||||
.calendar-today {
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
font-weight: 800;
|
|
||||||
color: $selected_fg_color !important;
|
|
||||||
|
|
||||||
&:hover,&:focus {
|
|
||||||
background-color:lighten($selected_bg_color, 3%);
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active,&:selected {
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
color: inherit;
|
|
||||||
|
|
||||||
&:hover,&:focus {
|
|
||||||
background-color:lighten($selected_bg_color, 3%);
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-day-with-events {
|
|
||||||
background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/calendar-today-light.svg"),url("resource:///org/gnome/shell/theme/calendar-today.svg"));
|
|
||||||
background-size: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.calendar-week-number {
|
|
||||||
@include fontsize($base_font_size - 4);
|
|
||||||
font-weight: bold;
|
|
||||||
font-feature-settings: "tnum";
|
|
||||||
margin: 6px;
|
|
||||||
padding: 0 $base_padding;
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: transparentize($fg_color, 0.9);
|
|
||||||
color: $insensitive_fg_color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Events */
|
|
||||||
.events-button {
|
|
||||||
@include card;
|
|
||||||
padding: $base_padding * 2;
|
|
||||||
|
|
||||||
.events-box {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.events-list {
|
|
||||||
spacing: 2 * $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.events-title {
|
|
||||||
@extend %heading;
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
margin-bottom: $base_margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.event-time {
|
|
||||||
@extend %numeric;
|
|
||||||
@extend %caption;
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* World clocks */
|
|
||||||
.world-clocks-button {
|
|
||||||
@include card;
|
|
||||||
padding: $base_padding * 2;
|
|
||||||
|
|
||||||
.world-clocks-grid {
|
|
||||||
spacing-rows: $base_padding;
|
|
||||||
spacing-columns: $base_padding * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// title
|
|
||||||
.world-clocks-header {
|
|
||||||
@extend %heading;
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// city label
|
|
||||||
.world-clocks-city {
|
|
||||||
color: $fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// timezone time
|
|
||||||
.world-clocks-time {
|
|
||||||
@extend %heading;
|
|
||||||
@extend %numeric;
|
|
||||||
color: $fg_color;
|
|
||||||
|
|
||||||
&:ltr {text-align: right;}
|
|
||||||
&:rtl {text-align: left;}
|
|
||||||
}
|
|
||||||
|
|
||||||
// timezone offset label
|
|
||||||
.world-clocks-timezone {
|
|
||||||
@extend %numeric;
|
|
||||||
@extend %caption;
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Weather */
|
|
||||||
.weather-button {
|
|
||||||
@include card;
|
|
||||||
padding: $base_padding * 2;
|
|
||||||
|
|
||||||
.weather-box {
|
|
||||||
spacing: $base_padding + $base_margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.weather-header-box {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.weather-header {
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
@extend %heading;
|
|
||||||
|
|
||||||
&.location {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.weather-grid {
|
|
||||||
spacing-rows: $base_padding;
|
|
||||||
spacing-columns: $base_padding * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.weather-forecast-time {
|
|
||||||
@extend %numeric;
|
|
||||||
@extend %caption;
|
|
||||||
color: darken($fg_color,30%);
|
|
||||||
padding-top: 0.2em;
|
|
||||||
padding-bottom: 0.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.weather-forecast-icon {
|
|
||||||
icon-size: $large_icon_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
.weather-forecast-temp {
|
|
||||||
@extend %heading;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/* Check Boxes */
|
|
||||||
|
|
||||||
// these are equal to the size of the SVG assets
|
|
||||||
$check_height: 24px;
|
|
||||||
$check_width: 24px;
|
|
||||||
|
|
||||||
|
|
||||||
.check-box {
|
|
||||||
StBoxLayout { spacing: .8em; }
|
|
||||||
StBin {
|
|
||||||
width: $check_width;
|
|
||||||
height: $check_height;
|
|
||||||
background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off.svg"));
|
|
||||||
}
|
|
||||||
&:focus StBin { background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/checkbox-off-focused-light.svg"), url("resource:///org/gnome/shell/theme/checkbox-off-focused.svg"));; }
|
|
||||||
&:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox.svg"); }
|
|
||||||
&:focus:checked StBin { background-image: url("resource:///org/gnome/shell/theme/checkbox-focused.svg"); }
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
/* Activities Ripple */
|
|
||||||
|
|
||||||
$ripple_size: 50px;
|
|
||||||
|
|
||||||
.ripple-box {
|
|
||||||
background-color: rgba(255,255,255,0.2);
|
|
||||||
box-shadow: 0 0 2px 2px rgba(255,255,255,0.2);
|
|
||||||
// plus + 2px for the border (box-shadow)
|
|
||||||
width: $ripple_size + 2px;
|
|
||||||
height: $ripple_size + 2px;
|
|
||||||
border-radius: 0 0 $ripple_size + 2px 0; // radius equals the size of the box to give us the curve
|
|
||||||
|
|
||||||
// just a simple change to the border radius position
|
|
||||||
&:rtl { border-radius: 0 0 0 $ripple_size + 2px; }
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/* Dash */
|
|
||||||
|
|
||||||
$dash_background_color: lighten($system_bg_color, 5%);
|
|
||||||
$dash_placeholder_size: 32px;
|
|
||||||
$dash_padding: $base_padding*2; // 12px
|
|
||||||
$dash_border_radius: $modal_radius + $dash_padding;
|
|
||||||
|
|
||||||
// container for the dash
|
|
||||||
#dash {
|
|
||||||
@extend %caption;
|
|
||||||
margin-top: $dash_padding;
|
|
||||||
|
|
||||||
.placeholder {
|
|
||||||
// background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
|
|
||||||
background-image:none;
|
|
||||||
background-size: contain;
|
|
||||||
height: $dash_placeholder_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-dash-drop-target {
|
|
||||||
width: $dash_placeholder_size;
|
|
||||||
height: $dash_placeholder_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Running app indicator (also shown in app grid)
|
|
||||||
.app-well-app-running-dot {
|
|
||||||
margin-bottom: 14px; // hardcoded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// background of the dash behind app icons
|
|
||||||
.dash-background {
|
|
||||||
background-color: $dash_background_color;
|
|
||||||
border-radius: $dash_border_radius;
|
|
||||||
padding: $dash_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
margin-bottom: $dash_padding;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border: 2px solid $hc_inset_color;
|
|
||||||
box-shadow:none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// items on the dash
|
|
||||||
.dash-item-container {
|
|
||||||
> * {margin: 0 2px;}
|
|
||||||
&:ltr{&:first-child {margin-left: 0;}}
|
|
||||||
&:rtl{&:first-child {margin-right: 0;}}
|
|
||||||
|
|
||||||
// each app item on the dash
|
|
||||||
.app-well-app .overview-icon {
|
|
||||||
padding: $base_padding;
|
|
||||||
border-radius: $base_border_radius*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// show apps button
|
|
||||||
.show-apps { @include overview_icon($osd_fg_color);}
|
|
||||||
|
|
||||||
.show-apps, .app-well-app {
|
|
||||||
padding-bottom: $dash_padding;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// separator between favourites and running apps
|
|
||||||
.dash-separator {
|
|
||||||
width: 1px;
|
|
||||||
margin: 0 $base_margin;
|
|
||||||
background-color: $borders_color;
|
|
||||||
margin-bottom: $dash_padding;
|
|
||||||
@if $is_highcontrast {
|
|
||||||
width: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OSD Tooltip
|
|
||||||
.dash-label {
|
|
||||||
@extend %tooltip;
|
|
||||||
-y-offset: $base_margin * 2; // distance from the dash edge
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
/* Modal Dialogs */
|
|
||||||
|
|
||||||
.headline {
|
|
||||||
@extend %title_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-dialog {
|
|
||||||
background-color: $bg_color;
|
|
||||||
border-radius: $modal_radius;
|
|
||||||
box-shadow: inset 0 0 0 1px $outer_borders_color;
|
|
||||||
|
|
||||||
.modal-dialog-content-box {
|
|
||||||
margin: 32px 40px;
|
|
||||||
spacing: 32px;
|
|
||||||
max-width: 28em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-dialog-linked-button {
|
|
||||||
@extend %bubble_button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End Session Dialog */
|
|
||||||
.end-session-dialog {
|
|
||||||
width: 30em;
|
|
||||||
|
|
||||||
.end-session-dialog-battery-warning,
|
|
||||||
.dialog-list-title {
|
|
||||||
color: $warning_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Message Dialog */
|
|
||||||
.message-dialog-content {
|
|
||||||
spacing: 18px;
|
|
||||||
|
|
||||||
.message-dialog-title {
|
|
||||||
text-align: center;
|
|
||||||
@extend %title_2;
|
|
||||||
|
|
||||||
&.lightweight { @extend %title_4;}
|
|
||||||
}
|
|
||||||
.message-dialog-description { text-align: center; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dialog List */
|
|
||||||
.dialog-list {
|
|
||||||
spacing: 18px;
|
|
||||||
|
|
||||||
.dialog-list-title {
|
|
||||||
text-align: center;
|
|
||||||
@extend %heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-list-scrollview { max-height: 200px; }
|
|
||||||
.dialog-list-box {
|
|
||||||
spacing: 1em;
|
|
||||||
|
|
||||||
.dialog-list-item {
|
|
||||||
spacing: 1em;
|
|
||||||
|
|
||||||
.dialog-list-item-title { font-weight: bold; }
|
|
||||||
.dialog-list-item-description {
|
|
||||||
color: darken($fg_color,5%);
|
|
||||||
@extend %caption;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Run Dialog */
|
|
||||||
.run-dialog {
|
|
||||||
.modal-dialog-content-box {
|
|
||||||
margin-top: 24px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
}
|
|
||||||
.run-dialog-entry { width: 20em; }
|
|
||||||
.run-dialog-description {
|
|
||||||
@extend %caption;
|
|
||||||
text-align: center;
|
|
||||||
color: darken($fg_color, 20%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Password or Authentication Dialog */
|
|
||||||
|
|
||||||
.prompt-dialog {
|
|
||||||
width: 28em;
|
|
||||||
|
|
||||||
.modal-dialog-content-box {
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt-dialog-password-grid {
|
|
||||||
spacing-rows: 8px;
|
|
||||||
spacing-columns: 4px;
|
|
||||||
|
|
||||||
.prompt-dialog-password-entry {
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
// 4px (spacing) + 16px (spinner-width)
|
|
||||||
&:ltr { margin-left: 20px; }
|
|
||||||
&:rtl { margin-right: 20px; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt-dialog-password-layout {
|
|
||||||
spacing: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt-dialog-password-entry {
|
|
||||||
width: 20em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt-dialog-error-label,
|
|
||||||
.prompt-dialog-info-label,
|
|
||||||
.prompt-dialog-null-label {
|
|
||||||
text-align: center;
|
|
||||||
@extend %caption;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt-dialog-error-label {
|
|
||||||
color: $warning_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Polkit Dialog */
|
|
||||||
|
|
||||||
.polkit-dialog-user-layout {
|
|
||||||
text-align: center;
|
|
||||||
spacing: 8px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
|
|
||||||
.polkit-dialog-user-root-label { color: $warning_color; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Audio selection dialog */
|
|
||||||
.audio-device-selection-dialog {
|
|
||||||
.modal-dialog-content-box { margin-bottom: 28px; }
|
|
||||||
.audio-selection-box { spacing: 20px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.audio-selection-device {
|
|
||||||
border-radius: $base_border_radius*2;
|
|
||||||
&:hover,&:focus { background-color: $hover_bg_color; }
|
|
||||||
&:active {
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
color: $selected_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.audio-selection-device-box {
|
|
||||||
padding: 20px;
|
|
||||||
spacing: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.audio-selection-device-icon {
|
|
||||||
icon-size: $base_icon_size * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Welcome dialog */
|
|
||||||
.welcome-dialog-image {
|
|
||||||
background-image: url("resource:///org/gnome/shell/theme/gnome-shell-start.svg");
|
|
||||||
background-size: contain;
|
|
||||||
/* Reasonable maximum dimensions */
|
|
||||||
height: 300px;
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Access portal dialog */
|
|
||||||
.access-dialog {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/* Entries */
|
|
||||||
|
|
||||||
StEntry {
|
|
||||||
@extend %entry;
|
|
||||||
|
|
||||||
StIcon.capslock-warning {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
warning-color: $warning_color;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
StIcon.peek-password {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
StLabel.hint-text {
|
|
||||||
margin-left: 2px;
|
|
||||||
color: transparentize($fg_color, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// hotplug
|
|
||||||
|
|
||||||
.hotplug-notification-item {
|
|
||||||
@extend %bubble_button;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hotplug-notification-item-icon {
|
|
||||||
icon-size: 24px;
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
// IBus Candidate Popup
|
|
||||||
|
|
||||||
.candidate-popup-boxpointer {
|
|
||||||
@extend .popup-menu-boxpointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.candidate-popup-content {
|
|
||||||
padding: $base_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
@extend .popup-menu-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.candidate-index {
|
|
||||||
padding: 0;
|
|
||||||
padding-right: $base_padding;
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.candidate-box {
|
|
||||||
padding: $base_padding $base_padding*2 $base_padding $base_padding*2;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
&:selected { background-color: $selected_bg_color; color: $selected_fg_color; }
|
|
||||||
&:hover { background-color: $hover_bg_color; color: $hover_fg_color; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.candidate-page-button-box {
|
|
||||||
height: 2em;
|
|
||||||
.vertical & { padding-top: $base_padding*2; }
|
|
||||||
.horizontal & { padding-left: $base_padding*2; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.candidate-page-button {
|
|
||||||
padding: $base_padding;
|
|
||||||
|
|
||||||
& StIcon { icon-size: $base_icon_size; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.candidate-page-button-previous { border-radius: $base_border_radius 0px 0px $base_border_radius; border-right-width: 0;box-shadow: none;}
|
|
||||||
.candidate-page-button-next { border-radius: 0px $base_border_radius $base_border_radius 0px;box-shadow: none;}
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
/* On-screen Keyboard */
|
|
||||||
|
|
||||||
$key_size: 1.2em;
|
|
||||||
$key_border_radius: $base_border_radius + 4px; // 12px
|
|
||||||
$key_bg_color: darken($osd_fg_color, 70%);
|
|
||||||
// $default_key_bg_color: darken($key_bg_color, 4%);
|
|
||||||
$default_key_bg_color: if($variant=='light', darken($key_bg_color, 11%), darken($key_bg_color, 10%));
|
|
||||||
|
|
||||||
|
|
||||||
// draw keys using button function
|
|
||||||
#keyboard {
|
|
||||||
// background-color: transparentize(if($variant=='light', darken($bg_color, 5%), darken($bg_color, 8%)), 0.1);
|
|
||||||
background-color: $osd_bg_color;
|
|
||||||
box-shadow: inset 0 1px 0 0 $osd_outer_borders_color;
|
|
||||||
|
|
||||||
.page-indicator {
|
|
||||||
padding: $base_padding;
|
|
||||||
|
|
||||||
.page-indicator-icon {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the container for individual keys
|
|
||||||
.key-container {
|
|
||||||
padding: $base_margin;
|
|
||||||
spacing: $base_margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the keys
|
|
||||||
.keyboard-key {
|
|
||||||
|
|
||||||
@include fontsize($base_font_size + 5);
|
|
||||||
font-weight: bold;
|
|
||||||
min-height: $key_size;
|
|
||||||
min-width: $key_size;
|
|
||||||
border-width: 1px;
|
|
||||||
border-style: solid;
|
|
||||||
border-radius: $key_border_radius;
|
|
||||||
box-shadow: 0 1px 0 0 $shadow_color;
|
|
||||||
|
|
||||||
@include keyboard_key(normal, $key_bg_color, $osd_fg_color);
|
|
||||||
|
|
||||||
&:focus { @include keyboard_key(focus);}
|
|
||||||
&:hover { @include keyboard_key(hover, $key_bg_color, $osd_fg_color);}
|
|
||||||
&:active { @include keyboard_key(active, $key_bg_color, $osd_fg_color); }
|
|
||||||
&:checked { @include keyboard_key(checked, $key_bg_color, $osd_fg_color); }
|
|
||||||
|
|
||||||
&:grayed { //FIXMEy
|
|
||||||
background-color: darken($bg_color, 3%);
|
|
||||||
color: $osd_fg_color;
|
|
||||||
border-color: $osd_borders_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// non-character keys
|
|
||||||
&.default-key {
|
|
||||||
@include keyboard_key(normal, $default_key_bg_color, $osd_fg_color);
|
|
||||||
&:hover {@include keyboard_key(hover, $default_key_bg_color, $osd_fg_color);}
|
|
||||||
&:active { @include keyboard_key(active, $default_key_bg_color, $osd_fg_color);}
|
|
||||||
&:checked { @include keyboard_key(checked, $default_key_bg_color, $osd_fg_color);}
|
|
||||||
border-radius: $key_border_radius;
|
|
||||||
|
|
||||||
// keys that may be latched: ctrl/alt/shift
|
|
||||||
&:latched {
|
|
||||||
border-color: lighten($selected_bg_color, 5%);
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// enter key is suggested-action
|
|
||||||
&.enter-key {
|
|
||||||
@include keyboard_key(normal, $selected_bg_color, $selected_fg_color);
|
|
||||||
&:hover { @include keyboard_key(hover, $selected_bg_color, $selected_fg_color);}
|
|
||||||
&:active {@include keyboard_key(active, $selected_bg_color, $selected_fg_color);}
|
|
||||||
&:checked {@include keyboard_key(checked, $selected_bg_color, $selected_fg_color);}
|
|
||||||
border-radius: $key_border_radius;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.shift-key-lowercase {}
|
|
||||||
|
|
||||||
// pressed shift has different style
|
|
||||||
&.shift-key-uppercase {
|
|
||||||
background-color: lighten($key_bg_color, 20%);
|
|
||||||
color: $osd_bg_color;
|
|
||||||
&:hover {
|
|
||||||
background-color: lighten($key_bg_color, 25%);
|
|
||||||
color: lighten($osd_bg_color, 5%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// size of icons on keys
|
|
||||||
StIcon { icon-size: 24px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// long press on a key popup
|
|
||||||
.keyboard-subkeys {
|
|
||||||
-arrow-border-radius: $base_border_radius*2;
|
|
||||||
-arrow-background-color: $osd_bg_color;
|
|
||||||
-arrow-border-width: 1px;
|
|
||||||
-arrow-border-color: lighten($osd_bg_color, 9%);
|
|
||||||
-arrow-base: 20px;
|
|
||||||
-arrow-rise: 10px;
|
|
||||||
-boxpointer-gap: $base_padding;
|
|
||||||
padding: $base_padding;
|
|
||||||
|
|
||||||
.keyboard-key {
|
|
||||||
@include keyboard_key(normal, $key_bg_color, $osd_fg_color);
|
|
||||||
|
|
||||||
&:focus { @include keyboard_key(focus);}
|
|
||||||
&:hover { @include keyboard_key(hover, $key_bg_color, $osd_fg_color);}
|
|
||||||
&:active { @include keyboard_key(active, $key_bg_color, $osd_fg_color); }
|
|
||||||
&:checked { @include keyboard_key(checked, $key_bg_color, $osd_fg_color); }
|
|
||||||
|
|
||||||
border-radius:$key_border_radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// emoji
|
|
||||||
.emoji-page {
|
|
||||||
.keyboard-key {
|
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
|
||||||
color: initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.emoji-panel {
|
|
||||||
.keyboard-key:latched {
|
|
||||||
border-color: lighten($selected_bg_color, 5%);
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// suggestions
|
|
||||||
.word-suggestions {
|
|
||||||
@include fontsize($base_font_size + 1);
|
|
||||||
spacing: 12px;
|
|
||||||
min-height: 17pt;
|
|
||||||
padding: $base_padding*2;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
|
|
||||||
// each suggestion
|
|
||||||
StButton {
|
|
||||||
margin: 0 3px;
|
|
||||||
min-width: 32px;
|
|
||||||
border-radius: $base_border_radius - 2px;
|
|
||||||
padding: 0px $base_padding*3;
|
|
||||||
|
|
||||||
@include keyboard_key(undecorated, $key_bg_color, $osd_fg_color);
|
|
||||||
|
|
||||||
&:focus { @include keyboard_key(focus);}
|
|
||||||
&:hover { @include keyboard_key(hover, $key_bg_color, $osd_fg_color);}
|
|
||||||
&:active { @include keyboard_key(active, $key_bg_color, $osd_fg_color); }
|
|
||||||
&:checked { @include keyboard_key(checked, $key_bg_color, $osd_fg_color); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
$_gdm_bg: $system_bg_color;
|
|
||||||
$_gdm_fg: white;
|
|
||||||
$_gdm_dialog_width: 23em;
|
|
||||||
|
|
||||||
// common style for gdm and lockscreen
|
|
||||||
.login-dialog,
|
|
||||||
.unlock-dialog {
|
|
||||||
|
|
||||||
.caps-lock-warning-label,
|
|
||||||
.login-dialog-message-warning {
|
|
||||||
color: $_gdm_fg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Login Dialog */
|
|
||||||
.login-dialog {
|
|
||||||
background-color: $_gdm_bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// buttons
|
|
||||||
.login-dialog-button {
|
|
||||||
@extend .button;
|
|
||||||
|
|
||||||
&.cancel-button,
|
|
||||||
&.switch-user-button,
|
|
||||||
&.login-dialog-session-list-button {
|
|
||||||
@extend .icon-button;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cancel-button {
|
|
||||||
padding: $base_padding*1.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-button-box {
|
|
||||||
width: $_gdm_dialog_width;
|
|
||||||
spacing: $base_padding*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-logo-bin {
|
|
||||||
margin:3em 0;
|
|
||||||
}
|
|
||||||
.login-dialog-banner { color: darken($_gdm_fg,10%); }
|
|
||||||
.login-dialog-banner-view { max-width: $_gdm_dialog_width; }
|
|
||||||
.login-dialog-message { text-align: center; }
|
|
||||||
.login-dialog-user-selection-box { padding: 100px 0px; }
|
|
||||||
|
|
||||||
.login-dialog-not-listed-label {
|
|
||||||
@include fontsize($base_font_size);
|
|
||||||
font-weight: bold;
|
|
||||||
color: darken($_gdm_fg,30%);
|
|
||||||
padding: $base_padding*2;
|
|
||||||
|
|
||||||
.login-dialog-not-listed-button:focus &,
|
|
||||||
.login-dialog-not-listed-button:hover & {
|
|
||||||
color: $_gdm_fg;
|
|
||||||
}
|
|
||||||
.login-dialog-not-listed-button:focus & {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-auth-list-view { -st-vfade-offset: 1em; }
|
|
||||||
.login-dialog-auth-list {
|
|
||||||
spacing: 6px;
|
|
||||||
margin-left: 2em;
|
|
||||||
}
|
|
||||||
.login-dialog-auth-list-title {
|
|
||||||
margin-left: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-auth-list-item {
|
|
||||||
border-radius: $base_border_radius*2;
|
|
||||||
padding: 4px;
|
|
||||||
color: darken($_gdm_fg,30%);
|
|
||||||
|
|
||||||
&:focus, &:selected {
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
color: $selected_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-auth-list-label {
|
|
||||||
@include fontsize($base_font_size + 2);
|
|
||||||
font-weight: bold;
|
|
||||||
padding-left: 15px;
|
|
||||||
|
|
||||||
&:ltr { padding-left: 14px; text-align: left; }
|
|
||||||
&:rtl { padding-right: 14px; text-align: right; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-user-list-view { -st-vfade-offset: 1em; }
|
|
||||||
|
|
||||||
.login-dialog-user-list {
|
|
||||||
spacing: 12px;
|
|
||||||
width: $_gdm_dialog_width;
|
|
||||||
|
|
||||||
.login-dialog-user-list-item {
|
|
||||||
border-radius: $base_border_radius + 4px;
|
|
||||||
padding: $base_padding;
|
|
||||||
background-color: transparentize($_gdm_fg, .95);
|
|
||||||
color: $_gdm_fg;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow:inset 0 0 0 1px $hc_inset_color;;
|
|
||||||
}
|
|
||||||
.user-widget .user-icon {
|
|
||||||
border: 4px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-timed-login-indicator {
|
|
||||||
height: 2px;
|
|
||||||
margin-top: 6px;
|
|
||||||
background-color: darken($_gdm_fg, 30%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus .login-dialog-timed-login-indicator { background-color: $selected_fg_color; }
|
|
||||||
}
|
|
||||||
|
|
||||||
&:expanded .login-dialog-user-list-item {
|
|
||||||
transition-duration: 300ms;
|
|
||||||
transition-timing-function: ease;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: transparentize($_gdm_fg, .9);
|
|
||||||
color: $_gdm_fg;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:selected {
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
color: $selected_fg_color;
|
|
||||||
&:hover { background-color: lighten($selected_bg_color,5%); }
|
|
||||||
}
|
|
||||||
|
|
||||||
&:logged-in {
|
|
||||||
.user-widget .user-icon {
|
|
||||||
border-color: $selected_bg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-prompt-layout {
|
|
||||||
spacing: $base_padding*2;
|
|
||||||
width: 26em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-dialog-prompt-entry {}
|
|
||||||
|
|
||||||
|
|
||||||
/* Screen Shield */
|
|
||||||
// a.k.a. the lockscreen
|
|
||||||
|
|
||||||
.unlock-dialog {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screen-shield-background { // just the shadow, really
|
|
||||||
background: black;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
#lockDialogGroup {
|
|
||||||
background-color: $_gdm_bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clock
|
|
||||||
.unlock-dialog-clock {
|
|
||||||
color: $_gdm_fg;
|
|
||||||
spacing: 2em;
|
|
||||||
|
|
||||||
.unlock-dialog-clock-time {
|
|
||||||
@extend %numeric;
|
|
||||||
@include fontsize(72);
|
|
||||||
font-weight: 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-dialog-clock-date {
|
|
||||||
@extend %title_1;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-dialog-clock-hint {
|
|
||||||
margin-top: 2em;
|
|
||||||
padding: $base_padding $base_padding*3;
|
|
||||||
border-radius: $base_border_radius*2;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notifications
|
|
||||||
#unlockDialogNotifications {
|
|
||||||
StButton#vhandle, StButton#hhandle {
|
|
||||||
background-color: transparentize($bg_color,0.7);
|
|
||||||
&:hover, &:focus { background-color: transparentize($bg_color,0.5); }
|
|
||||||
&:active { background-color: transparentize($selected_bg_color,0.5); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-dialog-notifications-container {
|
|
||||||
margin: 12px;
|
|
||||||
spacing: 6px;
|
|
||||||
width: $_gdm_dialog_width;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
.summary-notification-stack-scrollview {
|
|
||||||
padding-top: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notification,
|
|
||||||
.unlock-dialog-notification-source {
|
|
||||||
padding: 12px 16px;
|
|
||||||
border: none;
|
|
||||||
background-color: transparentize($_gdm_fg,0.9);
|
|
||||||
color: $_gdm_fg;
|
|
||||||
border-radius: $modal_radius;
|
|
||||||
|
|
||||||
&.critical { background-color: transparentize($_gdm_fg,0.8) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-dialog-notification-label {
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 0;
|
|
||||||
&:rtl { padding-right: 12px; padding-left: 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.unlock-dialog-notification-count-text {
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 0 12px;
|
|
||||||
color: $_gdm_fg;
|
|
||||||
background-color: transparentize($_gdm_fg, 0.9);
|
|
||||||
border-radius: 99px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// User Widget
|
|
||||||
.user-widget {
|
|
||||||
|
|
||||||
.user-widget-label {
|
|
||||||
color: $_gdm_fg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// layout of the user list
|
|
||||||
&.horizontal {
|
|
||||||
spacing: $base_padding*3;
|
|
||||||
.user-widget-label {
|
|
||||||
@extend %title_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-icon {
|
|
||||||
& StIcon {
|
|
||||||
padding: 12px;
|
|
||||||
icon-size: $base_icon_size*2;
|
|
||||||
width: $base_icon_size*3;
|
|
||||||
height: $base_icon_size*3;
|
|
||||||
background-color: transparentize($_gdm_fg, 0.9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// layout of the login prompt
|
|
||||||
&.vertical {
|
|
||||||
spacing: $base_padding*4;
|
|
||||||
|
|
||||||
.user-widget-label {
|
|
||||||
@extend %title_1;
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: .75em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-icon {
|
|
||||||
icon-size: $base_icon_size*10;
|
|
||||||
|
|
||||||
& StIcon {
|
|
||||||
padding: 32px;
|
|
||||||
icon-size: $base_icon_size*4;
|
|
||||||
background-color: transparentize($_gdm_fg, 0.9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
/* Looking Glass */
|
|
||||||
|
|
||||||
// Dialog
|
|
||||||
#LookingGlassDialog {
|
|
||||||
background-color: transparentize($bg_color,0.05);
|
|
||||||
border-radius: 0 0 $modal_radius $modal_radius;
|
|
||||||
border: 1px solid $outer_borders_color;
|
|
||||||
border-top-width: 0;
|
|
||||||
color: $fg_color;
|
|
||||||
padding: $base_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
box-shadow: 0 2px 4px 0 $shadow_color;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border: 2px solid $hc_inset_color;
|
|
||||||
background-color: $bg_color;
|
|
||||||
border-top-width: 0;
|
|
||||||
box-shadow:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > #Toolbar {
|
|
||||||
border: none;
|
|
||||||
padding: $base_padding;
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
spacing: $base_padding;
|
|
||||||
|
|
||||||
.lg-toolbar-button {
|
|
||||||
padding: $base_padding $base_padding*2;
|
|
||||||
@extend %button;
|
|
||||||
|
|
||||||
& > StIcon { icon-size: $base_icon_size; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.labels {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notebook-tab {
|
|
||||||
-natural-hpadding: $base_padding*2;
|
|
||||||
-minimum-hpadding: $base_padding*2;
|
|
||||||
@extend %button;
|
|
||||||
padding: $base_padding $base_padding*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
StBoxLayout#EvalBox { padding: 4px; spacing: $base_padding; padding: $base_padding; }
|
|
||||||
StBoxLayout#ResultsArea { spacing: $base_padding; padding: $base_padding; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-dialog {
|
|
||||||
|
|
||||||
StEntry {
|
|
||||||
min-height: 22px;
|
|
||||||
@extend %entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shell-link {
|
|
||||||
color: $link_color;
|
|
||||||
&:hover { color: lighten($link_color, 10%); }
|
|
||||||
&:active { color: darken($link_color, 10%); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.actor-link {
|
|
||||||
color: $insensitive_fg_color;
|
|
||||||
&:hover { color: lighten($insensitive_fg_color, 20%); }
|
|
||||||
&:active { color: darken($insensitive_fg_color, 20%); }
|
|
||||||
|
|
||||||
& StIcon { icon-size: 12px; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-completions-text {
|
|
||||||
@extend %caption;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-obj-inspector-title {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-obj-inspector-button {
|
|
||||||
border: 1px solid $borders_color;
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
&:hover { border: 1px solid $fg_color; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extensions
|
|
||||||
#lookingGlassExtensions { padding: $base_padding; }
|
|
||||||
|
|
||||||
.lg-extensions-list {
|
|
||||||
padding: $base_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-extension {
|
|
||||||
padding: $base_padding*2;
|
|
||||||
@include card;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-extension-name {
|
|
||||||
@extend %heading;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-extension-meta {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inspector
|
|
||||||
#LookingGlassPropertyInspector {
|
|
||||||
background: $bg_color;
|
|
||||||
border: 1px solid $borders_color;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
padding: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-debug-flag-button {
|
|
||||||
StLabel { padding: $base_padding, 2 * $base_padding; }
|
|
||||||
|
|
||||||
color: $fg_color;
|
|
||||||
&:hover { color: lighten($fg_color, 20%); }
|
|
||||||
&:active { color: darken($fg_color, 20%); }
|
|
||||||
}
|
|
||||||
|
|
||||||
.lg-debug-flags-header {
|
|
||||||
padding-top: 2 * $base_padding;
|
|
||||||
padding: $base_padding;
|
|
||||||
@extend %title_2;
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
/* Message List */
|
|
||||||
// a.k.a. notifications in the menu
|
|
||||||
|
|
||||||
// main list
|
|
||||||
.message-list {
|
|
||||||
width: 29em;
|
|
||||||
border: solid $borders_color;
|
|
||||||
|
|
||||||
// padding and margins to account for scrollbar
|
|
||||||
&:ltr {margin-left: 0; margin-right: $base_margin; padding-right: $base_padding; border-right-width: 1px; }
|
|
||||||
&:rtl {margin-right: 0; margin-left: $base_margin; padding-left: $base_padding; border-left-width: 1px; }
|
|
||||||
|
|
||||||
.message-list-placeholder {
|
|
||||||
@extend %title_2;
|
|
||||||
color: transparentize($insensitive_fg_color, .5);
|
|
||||||
|
|
||||||
// icon size and color
|
|
||||||
> StIcon {
|
|
||||||
icon-size: $base_icon_size*3; // 48px
|
|
||||||
margin-bottom: $base_margin*3;
|
|
||||||
-st-icon-style: symbolic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-list-sections {
|
|
||||||
spacing: $base_padding;
|
|
||||||
margin: 0;
|
|
||||||
padding-bottom: $base_padding;
|
|
||||||
|
|
||||||
// to account for scrollbar
|
|
||||||
&:ltr {margin-right: $base_margin * 3; }
|
|
||||||
&:rtl {margin-left: $base_margin * 3;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-list-section,
|
|
||||||
.message-list-section-list {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do-not-disturb + clear button
|
|
||||||
.message-list-controls {
|
|
||||||
// NOTE: remove the padding if notification_bubble could remove margin for drop shadow
|
|
||||||
padding: $base_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
@extend %heading;
|
|
||||||
|
|
||||||
.dnd-button {
|
|
||||||
// We need this because the focus outline isn't inset like for the buttons
|
|
||||||
// so the dnd button would grow when it gets focus if we didn't change only
|
|
||||||
// its color when focusing.
|
|
||||||
border-width: 2px;
|
|
||||||
border-color: transparent;
|
|
||||||
border-radius: 32px;
|
|
||||||
border-style: solid;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
border-color: transparentize($selected_bg_color, 0.4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// message bubbles
|
|
||||||
.message {
|
|
||||||
@include card;
|
|
||||||
|
|
||||||
// icon container
|
|
||||||
.message-icon-bin {
|
|
||||||
padding: ($base_padding * 3);
|
|
||||||
|
|
||||||
&:ltr {padding-right:$base_padding;}
|
|
||||||
&:rtl {padding-left:$base_padding;}
|
|
||||||
|
|
||||||
// icon size and color
|
|
||||||
> StIcon {
|
|
||||||
icon-size: $large_icon_size; // 32px
|
|
||||||
-st-icon-style: symbolic;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback
|
|
||||||
> .fallback-app-icon {
|
|
||||||
width: $base_icon_size;
|
|
||||||
height: $base_icon_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// content
|
|
||||||
.message-content {
|
|
||||||
spacing: 4px;
|
|
||||||
padding: ($base_padding*1.5);
|
|
||||||
margin-bottom: $base_margin*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// title
|
|
||||||
.message-title {
|
|
||||||
font-weight: bold;
|
|
||||||
/* HACK: the label should be baseline-aligned with a 1em label, fake this with some bottom padding */
|
|
||||||
padding-top: 0.57em;
|
|
||||||
}
|
|
||||||
|
|
||||||
// secondary container in title box
|
|
||||||
.message-secondary-bin {
|
|
||||||
padding: 0 $base_margin * 2;
|
|
||||||
|
|
||||||
// notification time stamp
|
|
||||||
> .event-time {
|
|
||||||
color: transparentize($fg_color, 0.5);
|
|
||||||
@include fontsize($base_font_size - 2);
|
|
||||||
/* HACK: the label should be baseline-aligned with a 1em label, fake this with some bottom padding */
|
|
||||||
padding-bottom: 0.13em;
|
|
||||||
|
|
||||||
&:ltr { text-align: right };
|
|
||||||
&:rtl { text-align: left };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// close button
|
|
||||||
.message-close-button {
|
|
||||||
color: $fg_color;
|
|
||||||
background-color: transparentize($fg_color, 0.9);
|
|
||||||
border-radius: 99px;
|
|
||||||
padding: $base_padding - 1px;
|
|
||||||
margin: 1px;
|
|
||||||
&:hover {background-color: transparentize($fg_color, 0.8);}
|
|
||||||
&:active {background-color: transparentize($fg_color, 0.9);}
|
|
||||||
|
|
||||||
& StIcon { icon-size: $base_icon_size; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// body
|
|
||||||
.message-body {color: darken($fg_color, 10%);}
|
|
||||||
}
|
|
||||||
|
|
||||||
// URLs in messages
|
|
||||||
.url-highlighter {
|
|
||||||
link-color: $link_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Media Controls */
|
|
||||||
.message-media-control {
|
|
||||||
padding: 0 $base_padding*3;
|
|
||||||
margin: $base_padding*2 0;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
color: $fg_color;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border: 1px solid $hc_inset_color;
|
|
||||||
margin: $base_padding*2 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// colors are lightened since the media controls are in a card
|
|
||||||
&:hover {
|
|
||||||
background-color: lighten($hover_bg_color, 5%);
|
|
||||||
color: $fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: lighten($active_bg_color, 5%);
|
|
||||||
color: $fg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:insensitive {
|
|
||||||
color: lighten($insensitive_fg_color, 5%);
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix margin for last button
|
|
||||||
&:last-child:ltr { margin-right: $base_margin*3; }
|
|
||||||
&:last-child:rtl { margin-left: $base_margin*3; }
|
|
||||||
|
|
||||||
& StIcon { icon-size: $base_icon_size; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// album-art
|
|
||||||
.media-message-cover-icon {
|
|
||||||
icon-size: $base_icon_size*3 !important; // 48px
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
|
|
||||||
// when there is no artwork
|
|
||||||
&.fallback {
|
|
||||||
color: darken($fg_color, 17%);
|
|
||||||
background-color: $bg_color;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
icon-size: $large_icon_size !important; // 32px
|
|
||||||
padding: ($base_padding*2 + 2); // 16px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
// Rubberband for select-area screenshots
|
|
||||||
.select-area-rubberband {
|
|
||||||
background-color: transparentize($selected_bg_color,0.7);
|
|
||||||
border: 1px solid $selected_bg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// User icon
|
|
||||||
.user-icon {
|
|
||||||
background-size: contain;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
border-radius: 99px;
|
|
||||||
icon-size: $base_icon_size * 4; // 64px
|
|
||||||
|
|
||||||
& StIcon {
|
|
||||||
background-color: transparentize($osd_fg_color,0.95);
|
|
||||||
border-radius: 99px;
|
|
||||||
padding: $base_padding * 2 ; // 12px
|
|
||||||
width: $base_icon_size * 2.5; height: $base_icon_size * 2.5; // 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.user-avatar {
|
|
||||||
box-shadow:inset 0 0 0 1px transparentize($osd_fg_color, 0.9);
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow:inset 0 0 0 1px $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox { background-color: black; }
|
|
||||||
.flashspot { background-color: white; }
|
|
||||||
|
|
||||||
// Hidden
|
|
||||||
.hidden { color: rgba(0,0,0,0);}
|
|
||||||
|
|
||||||
// Caps-lock warning
|
|
||||||
.caps-lock-warning-label {
|
|
||||||
text-align: center;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
@extend %caption;
|
|
||||||
color: $warning_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Workspace animation */
|
|
||||||
|
|
||||||
.workspace-animation {
|
|
||||||
background-color: $system_bg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tiled window previews */
|
|
||||||
.tile-preview {
|
|
||||||
background-color: transparentize($selected_bg_color,0.5);
|
|
||||||
border: 1px solid $selected_bg_color;
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/* Notifications & Message Tray */
|
|
||||||
|
|
||||||
$notification_banner_height: 64px;
|
|
||||||
$notification_banner_width: 34em;
|
|
||||||
$notification_banner_radius: $base_border_radius*1.5;
|
|
||||||
|
|
||||||
// Banner notifications
|
|
||||||
.notification-banner {
|
|
||||||
min-height: $notification_banner_height;
|
|
||||||
width: $notification_banner_width;
|
|
||||||
box-shadow: 0 2px 4px 2px $shadow_color;
|
|
||||||
border-radius: $notification_banner_radius;
|
|
||||||
margin: $base_margin;
|
|
||||||
|
|
||||||
.notification-actions {
|
|
||||||
spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.notification-button {
|
|
||||||
@extend %bubble_button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// counter
|
|
||||||
.summary-source-counter {
|
|
||||||
font-size: $base_font_size - 1pt;
|
|
||||||
font-weight: bold;
|
|
||||||
height: 1.6em;
|
|
||||||
width: 1.6em;
|
|
||||||
-shell-counter-overlap-x: 3px;
|
|
||||||
-shell-counter-overlap-y: 3px;
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
color: $selected_fg_color;
|
|
||||||
border: 2px solid $fg_color;
|
|
||||||
box-shadow: 0 2px 2px rgba(0,0,0,0.5);
|
|
||||||
border-radius: 0.9em; // should be 0.8 but whatever; wish I could do 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
// chat bubbles
|
|
||||||
.chat-body { spacing: 5px; }
|
|
||||||
.chat-response { margin: 5px; }
|
|
||||||
.chat-log-message { color: darken($fg_color,10%); }
|
|
||||||
.chat-new-group { padding-top: 1em; }
|
|
||||||
.chat-received {
|
|
||||||
padding-left: 4px;
|
|
||||||
&:rtl { padding-left: 0px; padding-right: 4px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-sent {
|
|
||||||
padding-left: 18pt;
|
|
||||||
color: lighten($fg_color, 15%);
|
|
||||||
&:rtl { padding-left: 0; padding-right: 18pt; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-meta-message {
|
|
||||||
padding-left: 4px;
|
|
||||||
@include fontsize($base_font_size - 2);
|
|
||||||
font-weight: bold;
|
|
||||||
color: lighten($fg_color,18%);
|
|
||||||
&:rtl { padding-left: 0; padding-right: 4px; }
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/* OSD */
|
|
||||||
|
|
||||||
$osd_levelbar_height:6px;
|
|
||||||
|
|
||||||
.osd-window {
|
|
||||||
@extend %osd_panel;
|
|
||||||
@extend %heading;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: bold;
|
|
||||||
spacing: $base_padding * 2; // 12px
|
|
||||||
padding: $base_padding * 2 $base_padding * 3;
|
|
||||||
& > * { spacing: 8px; }
|
|
||||||
margin-bottom: 4em;
|
|
||||||
|
|
||||||
StIcon { icon-size:$large_icon_size;}
|
|
||||||
|
|
||||||
StLabel {
|
|
||||||
&:ltr { margin-right: 6px; }
|
|
||||||
&:rtl { margin-left: 6px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.level {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
&:first-child { margin-bottom: 0px; }
|
|
||||||
|
|
||||||
height: $osd_levelbar_height;
|
|
||||||
min-width:$base_icon_size * 10;
|
|
||||||
-barlevel-height: $osd_levelbar_height;
|
|
||||||
-barlevel-background-color: transparentize($osd_fg_color, if($variant=='light', 0.7, 0.9));
|
|
||||||
-barlevel-active-background-color: $osd_fg_color;
|
|
||||||
-barlevel-overdrive-color: $destructive_color;
|
|
||||||
-barlevel-overdrive-separator-width: 3px;
|
|
||||||
&:ltr { margin-right: 6px; }
|
|
||||||
&:rtl { margin-left: 6px; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Monitor number label
|
|
||||||
.osd-monitor-label {
|
|
||||||
@extend %osd_panel;
|
|
||||||
border-radius: $modal_radius;
|
|
||||||
font-size: 3em;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: $base_margin * 3;
|
|
||||||
text-align: center;
|
|
||||||
min-width: 1.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pad OSD */
|
|
||||||
.pad-osd-window {
|
|
||||||
padding: 32px;
|
|
||||||
background-color: transparentize(#000, 0.2);
|
|
||||||
|
|
||||||
.pad-osd-title-box { spacing: 12px; }
|
|
||||||
.pad-osd-title-menu-box { spacing: 6px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.combo-box-label {
|
|
||||||
width: 15em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.resize-popup {
|
|
||||||
@extend %osd_panel;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
/* OVERVIEW */
|
|
||||||
|
|
||||||
.controls-manager, .secondary-monitor-workspaces {
|
|
||||||
spacing: $base_padding * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
#overviewGroup {
|
|
||||||
background-color: $system_bg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.overview-controls {
|
|
||||||
padding-bottom: 32px;
|
|
||||||
}
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
/* Top Bar */
|
|
||||||
// a.k.a. the panel
|
|
||||||
|
|
||||||
$panel_bg_color: #000;
|
|
||||||
$panel_fg_color: if($variant == 'light', lighten($bg_color, 10%), darken($fg_color, 5%));
|
|
||||||
$panel_height: 2.2em;
|
|
||||||
$panel_transition_duration: 250ms; // same as the overview transition duration
|
|
||||||
|
|
||||||
#panel {
|
|
||||||
background-color: $panel_bg_color;
|
|
||||||
font-weight: bold;
|
|
||||||
height: $panel_height;
|
|
||||||
@extend %numeric;
|
|
||||||
transition-duration: $panel_transition_duration;
|
|
||||||
|
|
||||||
// transparent panel on lock & login screens
|
|
||||||
&.unlock-screen,
|
|
||||||
&.login-screen,
|
|
||||||
&:overview {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// panel menus
|
|
||||||
.panel-button {
|
|
||||||
font-weight: bold;
|
|
||||||
color: $panel_fg_color;
|
|
||||||
-natural-hpadding: $base_padding * 2;
|
|
||||||
-minimum-hpadding: $base_padding;
|
|
||||||
transition-duration: 150ms;
|
|
||||||
border: 3px solid transparent;
|
|
||||||
border-radius: 99px;
|
|
||||||
|
|
||||||
&.clock-display {
|
|
||||||
.clock {
|
|
||||||
transition-duration: 150ms;
|
|
||||||
border: 3px solid transparent;
|
|
||||||
border-radius: 99px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px $screenshot_ui_button_red;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px $warning_color;
|
|
||||||
StBoxLayout { margin: 0 $base_padding; }
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator,
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
StBoxLayout {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
StIcon {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active, &:overview, &:focus, &:checked {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($panel_fg_color, 0.8);
|
|
||||||
|
|
||||||
// The clock display needs to have the background on .clock because
|
|
||||||
// we want to exclude the do-not-disturb indicator from the background
|
|
||||||
&.clock-display {
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
.clock {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($panel_fg_color, 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($screenshot_ui_button_red, 0.15);
|
|
||||||
}
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($warning_color, 0.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($panel_fg_color, 0.85);
|
|
||||||
&.clock-display {
|
|
||||||
box-shadow: none;
|
|
||||||
.clock {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($panel_fg_color, 0.85);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($screenshot_ui_button_red, 0.1);
|
|
||||||
}
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($warning_color, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:hover, &:overview:hover, &:focus:hover, &:checked:hover {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($panel_fg_color, 0.75);
|
|
||||||
&.clock-display {
|
|
||||||
box-shadow: none;
|
|
||||||
.clock {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($panel_fg_color, 0.75);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($screenshot_ui_button_red, 0.2);
|
|
||||||
}
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($warning_color, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// status area icons
|
|
||||||
.system-status-icon {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
padding: $base_padding - 1px;
|
|
||||||
margin: 0 $base_margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-status-indicators-box .system-status-icon,
|
|
||||||
.panel-status-menu-box .system-status-icon {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// app menu icon
|
|
||||||
.app-menu-icon {
|
|
||||||
-st-icon-style: symbolic;
|
|
||||||
// dimensions of the icon are hardcoded
|
|
||||||
}
|
|
||||||
|
|
||||||
&#panelActivities {
|
|
||||||
-natural-hpadding: $base_padding * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.unlock-screen,
|
|
||||||
&.login-screen,
|
|
||||||
&:overview {
|
|
||||||
.panel-button {
|
|
||||||
&:active, &:overview, &:focus, &:checked {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255,255,255, 0.15);
|
|
||||||
|
|
||||||
&.clock-display {
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
.clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255,255,255, 0.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($screenshot_ui_button_red, 0.15);
|
|
||||||
}
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($warning_color, 0.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255,255,255, 0.10);
|
|
||||||
&.clock-display {
|
|
||||||
box-shadow: none;
|
|
||||||
.clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255,255,255, 0.10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($screenshot_ui_button_red, 0.1);
|
|
||||||
}
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($warning_color, 0.1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:hover, &:overview:hover, &:focus:hover, &:checked:hover {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255,255,255, 0.2);
|
|
||||||
&.clock-display {
|
|
||||||
box-shadow: none;
|
|
||||||
.clock {
|
|
||||||
box-shadow: inset 0 0 0 100px rgba(255,255,255, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.screen-recording-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($screenshot_ui_button_red, 0.2);
|
|
||||||
}
|
|
||||||
&.screen-sharing-indicator {
|
|
||||||
box-shadow: inset 0 0 0 100px transparentize($warning_color, 0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-status-indicators-box,
|
|
||||||
.panel-status-menu-box {
|
|
||||||
spacing: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// spacing between power icon and (optional) percentage label
|
|
||||||
.power-status.panel-status-indicators-box {
|
|
||||||
spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// indicator for active
|
|
||||||
.screencast-indicator,
|
|
||||||
.remote-access-indicator { color: $warning_color; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// App Menu
|
|
||||||
#appMenu {
|
|
||||||
spacing: $base_padding;
|
|
||||||
.label-shadow { color: transparent; }
|
|
||||||
}
|
|
||||||
|
|
||||||
#appMenu .panel-status-menu-box {
|
|
||||||
padding: 0 $base_padding;
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Clock
|
|
||||||
|
|
||||||
.clock-display-box {
|
|
||||||
spacing: 2px;
|
|
||||||
|
|
||||||
.clock {
|
|
||||||
padding-left: $base_padding * 2;
|
|
||||||
padding-right: $base_padding * 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,162 +0,0 @@
|
|||||||
/* Popovers/Menus */
|
|
||||||
|
|
||||||
$menu_bg_color: $bg_color;
|
|
||||||
$menuitem_bg_color: lighten($menu_bg_color, 4%);
|
|
||||||
$menuitem_border_radius: $base_border_radius*1.5;
|
|
||||||
|
|
||||||
$submenu_bg_color: lighten($menu_bg_color, 7%);
|
|
||||||
|
|
||||||
// the popover itself
|
|
||||||
.popup-menu-boxpointer {
|
|
||||||
-arrow-rise: $base_margin+2px; // distance from the panel & screen edge
|
|
||||||
}
|
|
||||||
|
|
||||||
// container of the popover menu
|
|
||||||
.popup-menu {
|
|
||||||
min-width: 15em;
|
|
||||||
color: $fg_color;
|
|
||||||
|
|
||||||
//.popup-status-menu-item {font-weight: normal; color: pink;} //dunno what that is
|
|
||||||
&.panel-menu {
|
|
||||||
margin-bottom: 1.75em; // so it doesn't touch the bottom of the screen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// popover content
|
|
||||||
.popup-menu-content {
|
|
||||||
padding: $base_padding;
|
|
||||||
background-color: $bg_color;
|
|
||||||
border-radius: $modal_radius*1.25;
|
|
||||||
border: 1px solid $outer_borders_color;
|
|
||||||
box-shadow: 0 2px 4px 0 $shadow_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// menu items
|
|
||||||
.popup-menu-item {
|
|
||||||
@include menuitem($bg:$menu_bg_color);
|
|
||||||
|
|
||||||
border-radius: $menuitem_border_radius;
|
|
||||||
|
|
||||||
&:checked {
|
|
||||||
border-radius: $menuitem_border_radius $menuitem_border_radius 0 0 !important;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border: 1px solid $hc_inset_color;
|
|
||||||
border-bottom-width:0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add margin to switches in menu items
|
|
||||||
.toggle-switch {
|
|
||||||
&:ltr { margin-left: $base_margin;}
|
|
||||||
&:rtl { margin-right: $base_margin;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// all other graphical elements (sliders)
|
|
||||||
.popup-inactive-menu-item {
|
|
||||||
color: $fg_color;
|
|
||||||
&:insensitive { color: $insensitive_fg_color; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// symbolic icons in popover
|
|
||||||
.popup-menu-arrow,
|
|
||||||
.popup-menu-icon {
|
|
||||||
icon-size: 16px !important; // for some reason the variable doesn't work here
|
|
||||||
}
|
|
||||||
|
|
||||||
// popover submenus
|
|
||||||
.popup-sub-menu {
|
|
||||||
border-radius: 0 0 $menuitem_border_radius+1px $menuitem_border_radius+1px;
|
|
||||||
margin-bottom: $base_padding;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border: 1px solid $hc_inset_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-menu-ornament {
|
|
||||||
min-width: $base_icon_size !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// submenu specific styles
|
|
||||||
.popup-menu-item {
|
|
||||||
border-radius: 0;
|
|
||||||
@include menuitem($bg:$submenu_bg_color, $flat:false);
|
|
||||||
border-top-width:0;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-radius: 0 0 $menuitem_border_radius $menuitem_border_radius;
|
|
||||||
border-bottom-width:0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-menu-section {
|
|
||||||
.popup-menu-item:last-child {
|
|
||||||
&:hover,&:focus { border-radius: 0;}
|
|
||||||
}
|
|
||||||
&:last-child .popup-menu-item:last-child {
|
|
||||||
border-radius: 0 0 $menuitem_border_radius $menuitem_border_radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// container for radio and check boxes
|
|
||||||
.popup-menu-ornament {
|
|
||||||
@extend %heading;
|
|
||||||
width: 1.2em;
|
|
||||||
text-align: center !important;
|
|
||||||
|
|
||||||
&:ltr { text-align: right;}
|
|
||||||
&:rtl { text-align: left;}
|
|
||||||
}
|
|
||||||
|
|
||||||
// separator
|
|
||||||
.popup-separator-menu-item {
|
|
||||||
border:none !important;
|
|
||||||
|
|
||||||
.popup-separator-menu-item-separator {
|
|
||||||
height: 1px; //not really the whole box
|
|
||||||
background-color: $borders_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-menu-ornament {
|
|
||||||
width: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// separators in submenus
|
|
||||||
.popup-sub-menu & {
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
// account for ornament
|
|
||||||
&:ltr { margin-right: 2.5em;}
|
|
||||||
&:rtl { margin-left: 2.5em;}
|
|
||||||
|
|
||||||
.popup-separator-menu-item-separator {
|
|
||||||
background-color: $borders_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// desktop background menu
|
|
||||||
.background-menu {
|
|
||||||
-boxpointer-gap: 0px;
|
|
||||||
-arrow-rise: 0px; // hide the beak on the menu
|
|
||||||
}
|
|
||||||
|
|
||||||
// right-click (and panel) app menu
|
|
||||||
.app-menu {
|
|
||||||
max-width: 27.25em;
|
|
||||||
|
|
||||||
// this is unneeded at the top-level in this menu, hide it
|
|
||||||
.popup-menu-ornament { width: 0 !important; }
|
|
||||||
|
|
||||||
.popup-inactive-menu-item:first-child {
|
|
||||||
// "Open Windows" label
|
|
||||||
> StLabel {
|
|
||||||
@extend %caption_heading;
|
|
||||||
&:ltr {margin-right: $base_margin*2;}
|
|
||||||
&:rtl {margin-left: $base_margin*2;}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
.quick-settings {
|
|
||||||
padding: $base_padding*3;
|
|
||||||
border-radius: $modal_radius*2.25;
|
|
||||||
|
|
||||||
.icon-button, .button {
|
|
||||||
padding: $base_padding*1.75;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-settings-grid {
|
|
||||||
spacing-rows: $base_padding*2;
|
|
||||||
spacing-columns: $base_padding*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-toggle, .quick-menu-toggle {
|
|
||||||
border-radius: 99px;
|
|
||||||
min-width: 12em;
|
|
||||||
max-width: 12em;
|
|
||||||
min-height: 48px;
|
|
||||||
border:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-toggle {
|
|
||||||
&:checked { @include button(default, $c:$selected_bg_color); }
|
|
||||||
|
|
||||||
& > StBoxLayout { spacing: $base_padding*1.5; }
|
|
||||||
|
|
||||||
/* Move padding into the box; this is to allow menu arrows
|
|
||||||
to extend to the border */
|
|
||||||
&.button { padding: 0; }
|
|
||||||
& > StBoxLayout { padding: 0 $base_padding*2; }
|
|
||||||
&:ltr > StBoxLayout { padding-left: $base_padding*2.5; }
|
|
||||||
&:rtl > StBoxLayout { padding-right: $base_padding*2.5; }
|
|
||||||
|
|
||||||
.quick-toggle-title { font-weight: bold; }
|
|
||||||
|
|
||||||
& StBoxLayout > .quick-toggle-subtitle {
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-toggle-icon { icon-size: $base_icon_size; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-menu-toggle {
|
|
||||||
& .quick-toggle {
|
|
||||||
min-width: auto;
|
|
||||||
max-width: auto;
|
|
||||||
|
|
||||||
&:ltr { border-radius: 99px 0 0 99px; }
|
|
||||||
&:rtl { border-radius: 0 99px 99px 0; }
|
|
||||||
|
|
||||||
&:ltr:last-child { border-radius: 99px; }
|
|
||||||
&:rtl:last-child { border-radius: 99px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
& .quick-toggle-arrow {
|
|
||||||
padding: $base_padding $base_padding*1.75;
|
|
||||||
border-width: 0;
|
|
||||||
|
|
||||||
&:checked { @include button(default, $c:$selected_bg_color); }
|
|
||||||
|
|
||||||
&:ltr {
|
|
||||||
border-radius: 0 99px 99px 0;
|
|
||||||
border-left-width: 1px;
|
|
||||||
}
|
|
||||||
&:rtl {
|
|
||||||
border-radius: 99px 0 0 99px;
|
|
||||||
border-right-width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-slider {
|
|
||||||
& > StBoxLayout { spacing: $base_padding; }
|
|
||||||
|
|
||||||
.icon-button { padding: $base_padding; }
|
|
||||||
|
|
||||||
.slider-bin {
|
|
||||||
&:focus {@include button(focus);}
|
|
||||||
min-height: 16px; // slider size
|
|
||||||
padding: $base_padding;
|
|
||||||
border-radius: 99px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-toggle-menu {
|
|
||||||
@include card;
|
|
||||||
border-radius: $base_border_radius*3;
|
|
||||||
padding: $base_padding*2;
|
|
||||||
margin: $base_padding*2 $base_padding*3 0;
|
|
||||||
|
|
||||||
.popup-menu-item > StIcon { -st-icon-style: symbolic; }
|
|
||||||
|
|
||||||
& .header {
|
|
||||||
spacing-rows: 0.5 * $base_padding;
|
|
||||||
spacing-columns: $base_padding*2;
|
|
||||||
padding-bottom: 2 * $base_padding;
|
|
||||||
|
|
||||||
& .icon {
|
|
||||||
icon-size: $base_icon_size*1.5; // a non-standard symbolic size but ok
|
|
||||||
border-radius: 999px;
|
|
||||||
padding: 1.5 * $base_padding;
|
|
||||||
background-color: transparentize($fg_color, 0.8);
|
|
||||||
|
|
||||||
&.active { background-color: $selected_bg_color;}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .title {
|
|
||||||
@extend %title_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .subtitle {
|
|
||||||
@extend %caption_heading;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-toggle-menu-container {
|
|
||||||
}
|
|
||||||
|
|
||||||
.quick-settings-system-item {
|
|
||||||
& > StBoxLayout { spacing: 2 * $base_padding; }
|
|
||||||
|
|
||||||
& .power-item {
|
|
||||||
min-height: 0;
|
|
||||||
min-width: 0;
|
|
||||||
|
|
||||||
&:insensitive {
|
|
||||||
@include button(normal);
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nm-network-item {
|
|
||||||
.wireless-secure-icon { icon-size: 0.5 * $base_icon_size; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.bt-device-item {
|
|
||||||
.popup-menu-icon { -st-icon-style: symbolic; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.bt-menu-placeholder {
|
|
||||||
@extend %title_4;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
padding: 2em 4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-subtitle { color: transparentize($fg_color, 0.5); }
|
|
||||||
|
|
||||||
// background apps
|
|
||||||
|
|
||||||
.background-apps-quick-toggle {
|
|
||||||
min-height: 40px;
|
|
||||||
background-color: transparent;
|
|
||||||
|
|
||||||
& StIcon { icon-size: $base_icon_size !important; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.background-app-item {
|
|
||||||
& .title { @extend %heading; }
|
|
||||||
& .subtitle { @extend %caption; }
|
|
||||||
& .popup-menu-icon {
|
|
||||||
icon-size: $large_icon_size !important;
|
|
||||||
-st-icon-style: regular !important;
|
|
||||||
}
|
|
||||||
& .close-button {
|
|
||||||
@extend .icon-button;
|
|
||||||
padding: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.popup-inactive-menu-item { color: $fg_color; }
|
|
||||||
}
|
|
||||||
@@ -1,204 +0,0 @@
|
|||||||
// Screenshot UI
|
|
||||||
.icon-label-button-container {
|
|
||||||
spacing: $base_padding;
|
|
||||||
@extend %caption;
|
|
||||||
|
|
||||||
StIcon { icon-size: 32px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
$screenshot_ui_panel_padding: $base_padding*3;
|
|
||||||
$screenshot_ui_shot_cast_margin: 21px;
|
|
||||||
$screenshot_ui_panel_border_radius: $modal_radius + $screenshot_ui_shot_cast_margin;
|
|
||||||
$screenshot_ui_shot_cast_spacing: 3px;
|
|
||||||
|
|
||||||
$screenshot_ui_button_red: $error_color;
|
|
||||||
|
|
||||||
.screenshot-ui-panel {
|
|
||||||
@extend %osd_panel;
|
|
||||||
border-radius: $screenshot_ui_panel_border_radius;
|
|
||||||
padding: $screenshot_ui_panel_padding;
|
|
||||||
// Reduce the bottom padding a little to accommodate the large capture button.
|
|
||||||
padding-bottom: $screenshot_ui_panel_padding - 6px;
|
|
||||||
margin-bottom: 4em;
|
|
||||||
spacing: $base_padding * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-close-button {
|
|
||||||
@extend .window-close; // copy window close button
|
|
||||||
padding: $base_padding !important; // but with more padding
|
|
||||||
margin-top: 12px;
|
|
||||||
box-shadow: 0 2px 4px 0 $shadow_color;
|
|
||||||
&.left { margin-left: 12px;}
|
|
||||||
&.right { margin-right: 12px;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-type-button {
|
|
||||||
@extend %osd_button;
|
|
||||||
min-width: 48px;
|
|
||||||
padding: $base_padding * 2 $base_padding * 3 !important;
|
|
||||||
border-radius: $screenshot_ui_panel_border_radius - $screenshot_ui_panel_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-capture-button {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 99px;
|
|
||||||
border: 4px $osd_fg_color;
|
|
||||||
padding: 4px;
|
|
||||||
|
|
||||||
.screenshot-ui-capture-button-circle {
|
|
||||||
background-color: $osd_fg_color;
|
|
||||||
transition-duration: 200ms;
|
|
||||||
&:hover, &:focus { background-color: $hover_bg_color;}
|
|
||||||
border-radius: 99px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover, &:focus {
|
|
||||||
.screenshot-ui-capture-button-circle {
|
|
||||||
background-color: darken($osd_fg_color, 15%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
.screenshot-ui-capture-button-circle {
|
|
||||||
background-color: darken($osd_fg_color, 50%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:cast {
|
|
||||||
.screenshot-ui-capture-button-circle {
|
|
||||||
background-color: $screenshot_ui_button_red;
|
|
||||||
}
|
|
||||||
&:hover, &:focus {
|
|
||||||
.screenshot-ui-capture-button-circle {
|
|
||||||
background-color: lighten($screenshot_ui_button_red, 5%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
.screenshot-ui-capture-button-circle {
|
|
||||||
background-color: darken($screenshot_ui_button_red, 7%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-shot-cast-container {
|
|
||||||
background-color: lighten($osd_bg_color,5%);
|
|
||||||
border-radius: $modal_radius;
|
|
||||||
padding: $screenshot_ui_shot_cast_spacing;
|
|
||||||
spacing: $screenshot_ui_shot_cast_spacing;
|
|
||||||
|
|
||||||
&:ltr { margin-left: $screenshot_ui_shot_cast_margin - $screenshot_ui_panel_padding;}
|
|
||||||
&:rtl { margin-right: $screenshot_ui_shot_cast_margin - $screenshot_ui_panel_padding;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-shot-cast-button {
|
|
||||||
padding: $base_padding $base_padding*2;
|
|
||||||
background-color: transparent;
|
|
||||||
&:hover, &:focus { background-color: lighten($osd_bg_color, 10%);}
|
|
||||||
&:active { background-color: lighten($active_bg_color,5%);}
|
|
||||||
&:checked { background-color: white;color: black;}
|
|
||||||
&:insensitive { color: transparentize($osd_fg_color, 0.5);}
|
|
||||||
|
|
||||||
border-radius: $modal_radius - $screenshot_ui_shot_cast_spacing;
|
|
||||||
|
|
||||||
StIcon { icon-size: $base_icon_size;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-show-pointer-button {
|
|
||||||
@extend %osd_button;
|
|
||||||
border-radius: 99px;
|
|
||||||
padding: $base_padding * 2 !important;
|
|
||||||
StIcon { icon-size: $base_icon_size;}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-area-indicator-shade {
|
|
||||||
background-color: rgba(0,0,0,.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-area-selector {
|
|
||||||
.screenshot-ui-area-indicator-shade {
|
|
||||||
background-color: rgba(0,0,0,.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-area-indicator-selection {
|
|
||||||
border: 2px white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-area-selector-handle {
|
|
||||||
border-radius: 99px;
|
|
||||||
background-color: white;
|
|
||||||
box-shadow: 0 1px 3px 2px rgba(0,0,0,0.2);
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-window-selector {
|
|
||||||
background-color: $system_bg_color;
|
|
||||||
|
|
||||||
.screenshot-ui-window-selector-window-container {
|
|
||||||
margin: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:primary-monitor {
|
|
||||||
.screenshot-ui-window-selector-window-container {
|
|
||||||
// Make some room for the panel.
|
|
||||||
margin-bottom: 200px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-window-selector-window-border {
|
|
||||||
transition-duration: 200ms;
|
|
||||||
border-radius: $modal_radius;
|
|
||||||
border: 6px transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-window-selector-check {
|
|
||||||
transition-duration: 200ms;
|
|
||||||
color: transparent;
|
|
||||||
border-radius: 99px;
|
|
||||||
border-width: 12px;
|
|
||||||
icon-size: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-window-selector-window {
|
|
||||||
&:hover {
|
|
||||||
.screenshot-ui-window-selector-window-border {
|
|
||||||
border-color: darken($selected_bg_color, 15%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:checked {
|
|
||||||
.screenshot-ui-window-selector-window-border {
|
|
||||||
border-color: $selected_bg_color;
|
|
||||||
background-color: transparentize($selected_bg_color, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-window-selector-check {
|
|
||||||
color: $selected_fg_color;
|
|
||||||
background-color: $selected_bg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-screen-selector {
|
|
||||||
transition-duration: 200ms;
|
|
||||||
background-color: rgba(0,0,0,.5);
|
|
||||||
|
|
||||||
&:hover { background-color: rgba(0,0,0,.3);}
|
|
||||||
&:active { background-color: rgba(0,0,0,.7);}
|
|
||||||
&:checked {
|
|
||||||
background-color: transparent;
|
|
||||||
border: 2px white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.screenshot-ui-tooltip {
|
|
||||||
color: $osd_fg_color;
|
|
||||||
background-color: $osd_bg_color;
|
|
||||||
border-radius: 99px;
|
|
||||||
padding: $base_padding $base_padding * 2;
|
|
||||||
text-align: center;
|
|
||||||
-y-offset: 24px;
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* Scrollbars */
|
|
||||||
|
|
||||||
StScrollView {
|
|
||||||
&.vfade { -st-vfade-offset: 68px; }
|
|
||||||
&.hfade { -st-hfade-offset: 68px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
StScrollBar {
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
StScrollView & {
|
|
||||||
min-width: 8px;
|
|
||||||
min-height: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
StBin#trough {
|
|
||||||
border-radius: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
StButton#vhandle, StButton#hhandle {
|
|
||||||
border-radius: 8px;
|
|
||||||
background-color: mix($fg_color, $bg_color, 30%);
|
|
||||||
border: 3px solid transparent; //would be nice to margin or at least to transparent
|
|
||||||
transition: 500ms all ease;
|
|
||||||
&:hover {background-color: mix($fg_color, $bg_color, 50%);}
|
|
||||||
&:active {background-color: mix($fg_color, $bg_color, 40%);}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
// Search entry
|
|
||||||
.search-entry {
|
|
||||||
border-radius: 99px;
|
|
||||||
margin-top: $base_padding*2;
|
|
||||||
margin-bottom: $base_padding;
|
|
||||||
width: 24em;
|
|
||||||
|
|
||||||
.search-entry-icon {
|
|
||||||
icon-size: $base_icon_size;
|
|
||||||
margin-top: 2px; // center vertically
|
|
||||||
padding: 0 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/* Search */
|
|
||||||
|
|
||||||
// search overview container
|
|
||||||
#searchResults {
|
|
||||||
margin: 0 $base_margin;
|
|
||||||
}
|
|
||||||
|
|
||||||
#searchResultsContent {
|
|
||||||
max-width: 1072px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search results sections "the boxes"
|
|
||||||
.search-section {
|
|
||||||
// This should be equal to #searchResultsContent spacing
|
|
||||||
spacing: $base_padding*3;
|
|
||||||
|
|
||||||
// separator (unstyled)
|
|
||||||
.search-section-separator {
|
|
||||||
height: $base_margin*2; // use it as a spacer
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// content
|
|
||||||
.search-section-content {
|
|
||||||
background-color: lighten($system_bg_color, 5%);
|
|
||||||
border-radius: $modal_radius*1.5;
|
|
||||||
box-shadow:inset 0 0 0 1px solid $outer_borders_color;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
padding: $base_padding*2;
|
|
||||||
margin:0 $base_margin*3;
|
|
||||||
}
|
|
||||||
|
|
||||||
%search_section_content_item {
|
|
||||||
@include tile_button($osd_fg_color);
|
|
||||||
border-radius: $base_border_radius+3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "no results" text
|
|
||||||
.search-statustext {
|
|
||||||
@extend %title_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-search-results {
|
|
||||||
spacing: $base_padding*5;
|
|
||||||
margin:0 $base_margin*3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search results with icons
|
|
||||||
.grid-search-result {
|
|
||||||
@extend .app-well-app;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search result provider
|
|
||||||
.search-provider-icon {
|
|
||||||
@extend %search_section_content_item;
|
|
||||||
&:ltr {margin-right: $base_margin;}
|
|
||||||
&:rtl {margin-left: $base_margin;}
|
|
||||||
|
|
||||||
// content
|
|
||||||
.list-search-provider-content {
|
|
||||||
spacing: $base_padding * 2;
|
|
||||||
|
|
||||||
// provider labels
|
|
||||||
.list-search-provider-details {
|
|
||||||
width: 120px;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// search results list
|
|
||||||
.list-search-results {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search result listitem
|
|
||||||
.list-search-result {
|
|
||||||
@extend %search_section_content_item;
|
|
||||||
|
|
||||||
// content
|
|
||||||
.list-search-result-content {
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// list item title (with leading icon)
|
|
||||||
.list-search-result-title {
|
|
||||||
spacing: $base_padding * 2;
|
|
||||||
// font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
// list item description
|
|
||||||
.list-search-result-description {
|
|
||||||
color: $osd_insensitive_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/* Slider */
|
|
||||||
|
|
||||||
$slider_size: 16px;
|
|
||||||
|
|
||||||
.slider {
|
|
||||||
// slider trough
|
|
||||||
-barlevel-height: 4px;
|
|
||||||
-barlevel-background-color: if($variant == 'light', transparentize($fg_color, 0.6), transparentize($fg_color, 0.8)); //background of the trough
|
|
||||||
-barlevel-border-width: 2px;
|
|
||||||
-barlevel-border-color: transparent; // trough border color
|
|
||||||
// fill style
|
|
||||||
-barlevel-active-background-color: $selected_bg_color;
|
|
||||||
-barlevel-active-border-color: transparent;
|
|
||||||
// overfill style (red in this case)
|
|
||||||
-barlevel-overdrive-color: $destructive_color;
|
|
||||||
-barlevel-overdrive-border-color: transparent; //trough border when red;
|
|
||||||
-barlevel-overdrive-separator-width:1px;
|
|
||||||
// slider handler
|
|
||||||
-slider-handle-radius: $slider_size * 0.5; // half the size of the size
|
|
||||||
-slider-handle-border-width: 0;
|
|
||||||
-slider-handle-border-color: transparent; // because 0 width
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
/* App Switcher */
|
|
||||||
|
|
||||||
// same as dash
|
|
||||||
$switcher_padding: $base_padding*2;
|
|
||||||
|
|
||||||
|
|
||||||
// the full screen container of the switcher
|
|
||||||
.switcher-popup {
|
|
||||||
padding: 0;
|
|
||||||
spacing: $base_padding * 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// switcher onscreen panel
|
|
||||||
.switcher-list {
|
|
||||||
@extend %osd_panel;
|
|
||||||
padding: $switcher_padding;
|
|
||||||
border-radius: $modal_radius+$switcher_padding;
|
|
||||||
box-shadow: 0 8px 8px 0 $shadow_color;
|
|
||||||
|
|
||||||
// container for items in list
|
|
||||||
.switcher-list-item-container {
|
|
||||||
spacing: $base_padding * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// each item in the list
|
|
||||||
.item-box {
|
|
||||||
@include tile_button($osd_fg_color);
|
|
||||||
// override over style so mouse doesn't steal focus
|
|
||||||
&:hover {background: none;}
|
|
||||||
@if $is_highcontrast {
|
|
||||||
box-shadow: inset 0 0 0 999px transparentize($hc_inset_color,0.2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
|
||||||
width: 1px;
|
|
||||||
background: $borders_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
// container of thumbnails
|
|
||||||
.thumbnail-box {
|
|
||||||
padding: 2px;
|
|
||||||
spacing: $base_padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// window thumbnail itself
|
|
||||||
.thumbnail {
|
|
||||||
width: 256px; // equal to THUMBNAIL_DEFAULT_SIZE in altTab.js
|
|
||||||
border-radius:$base_border_radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// arrow if app has multiple windows
|
|
||||||
.switcher-arrow {
|
|
||||||
border-color: transparentize($osd_fg_color, 0.2);
|
|
||||||
color: transparentize($osd_fg_color, 0.2);
|
|
||||||
|
|
||||||
&:highlighted {
|
|
||||||
border-color: $osd_fg_color;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input Source Switcher
|
|
||||||
.input-source-switcher-symbol {
|
|
||||||
font-size: 34pt;
|
|
||||||
width: 96px;
|
|
||||||
height: 96px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Window cycler highlight
|
|
||||||
.cycler-highlight {
|
|
||||||
border: 5px solid $selected_bg_color;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/* Switches */
|
|
||||||
|
|
||||||
// these are equal to the size of the SVG assets
|
|
||||||
$switch_height: 26px;
|
|
||||||
$switch_width: 48px;
|
|
||||||
|
|
||||||
.toggle-switch {
|
|
||||||
color: $fg_color;
|
|
||||||
height: $switch_height;
|
|
||||||
width: $switch_width;
|
|
||||||
background-size: contain;
|
|
||||||
background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-off-light.svg"),url("resource:///org/gnome/shell/theme/toggle-off.svg"));
|
|
||||||
&:checked {
|
|
||||||
background-image: if($variant == 'light', url("resource:///org/gnome/shell/theme/toggle-on-light.svg"),url("resource:///org/gnome/shell/theme/toggle-on.svg"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/* Window Picker */
|
|
||||||
|
|
||||||
$window_picker_spacing: $base_padding; // 6px
|
|
||||||
$window_picker_padding: $base_padding * 2; // 12px
|
|
||||||
|
|
||||||
$window_thumbnail_label_color: transparentize($osd_bg_color, 0.4);
|
|
||||||
|
|
||||||
$window_close_button_color: transparentize(lighten($osd_bg_color, 7%), .02);
|
|
||||||
$window_close_button_size: 30px;
|
|
||||||
$window_close_button_padding: 3px;
|
|
||||||
|
|
||||||
// Window picker
|
|
||||||
.window-picker {
|
|
||||||
// Space between window thumbnails
|
|
||||||
spacing: $window_picker_spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Window titles
|
|
||||||
.window-caption {
|
|
||||||
@extend %tooltip;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close button
|
|
||||||
.window-close {
|
|
||||||
background-color: $window_close_button_color;
|
|
||||||
color: $osd_fg_color;
|
|
||||||
border-radius: 99px;
|
|
||||||
box-shadow: 0 2px 4px 0 $shadow_color;
|
|
||||||
padding: $window_close_button_padding;
|
|
||||||
height: $window_close_button_size;
|
|
||||||
width: $window_close_button_size;
|
|
||||||
transition-duration: 100ms;
|
|
||||||
|
|
||||||
& StIcon { icon-size: 24px; } // uses non standard icon size
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: lighten($window_close_button_color, 7%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: lighten($window_close_button_color, 13%);
|
|
||||||
}
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border:2px solid $outer_borders_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-background {
|
|
||||||
// keep in sync with BACKGROUND_CORNER_RADIUS_PIXELS in workspace.js
|
|
||||||
border-radius: 30px;
|
|
||||||
background-color: $invisible_occluded_bg_color;
|
|
||||||
box-shadow: 0 4px 16px 4px transparentize(darken($osd_bg_color, 30%), 0.7);
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/* Workspace Switcher */
|
|
||||||
|
|
||||||
$ws_indicator_height: $large_icon_size;
|
|
||||||
$ws_dot_active: $ws_indicator_height / 3;
|
|
||||||
$ws_dot_inactive: $ws_indicator_height / 6;
|
|
||||||
|
|
||||||
.workspace-switcher {
|
|
||||||
@extend %osd_panel;
|
|
||||||
margin-bottom: 4em;
|
|
||||||
spacing: $base_padding * 2;
|
|
||||||
padding: $base_padding * 2 $base_padding * 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ws-switcher-indicator {
|
|
||||||
background-color: transparentize($osd_fg_color,0.5);
|
|
||||||
padding: $ws_dot_inactive / 2;
|
|
||||||
margin: ($ws_indicator_height - $ws_dot_inactive) / 2;
|
|
||||||
border-radius: $ws_indicator_height;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color: $osd_fg_color;
|
|
||||||
padding: $ws_dot_active / 2;
|
|
||||||
margin: ($ws_indicator_height - $ws_dot_active) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
/* Workspace pager */
|
|
||||||
|
|
||||||
// thumbnails in overview
|
|
||||||
.workspace-thumbnails {
|
|
||||||
visible-width: 32px; //amount visible before hover
|
|
||||||
spacing: $base_padding;
|
|
||||||
padding: $base_padding;
|
|
||||||
|
|
||||||
.workspace-thumbnail {
|
|
||||||
color: $osd_fg_color;
|
|
||||||
background-color: lighten($system_bg_color, 10%);
|
|
||||||
border-radius: $base_border_radius*0.5;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
|
|
||||||
@if $is_highcontrast {
|
|
||||||
border-color: $hc_inset_color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// drag and drop indicator
|
|
||||||
.placeholder {
|
|
||||||
background-image: url("resource:///org/gnome/shell/theme/workspace-placeholder.svg");
|
|
||||||
background-size: contain;
|
|
||||||
width: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// selected indicator
|
|
||||||
.workspace-thumbnail-indicator {
|
|
||||||
border: 3px solid $selected_bg_color;
|
|
||||||
border-radius: $base_border_radius;
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
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-lock.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/_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/_quick-settings.scss',
|
|
||||||
'gnome-shell-sass/widgets/_screenshot.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/_window-picker.scss',
|
|
||||||
'gnome-shell-sass/widgets/_workspace-switcher.scss',
|
|
||||||
'gnome-shell-sass/widgets/_workspace-thumbnails.scss'
|
|
||||||
)
|
|
||||||
|
|
||||||
theme_data = [
|
|
||||||
'classic-process-working.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)
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
include $(top_srcdir)/include.mk
|
||||||
|
|
||||||
|
dist_extension_DATA = extension.js stylesheet.css
|
||||||
|
nodist_extension_DATA = metadata.json $(EXTRA_EXTENSION)
|
||||||
|
|
||||||
|
EXTRA_DIST = metadata.json.in
|
||||||
|
|
||||||
|
metadata.json: metadata.json.in $(top_builddir)/config.status
|
||||||
|
$(AM_V_GEN) sed -e "s|[@]uuid@|$(uuid)|" \
|
||||||
|
-e "s|[@]shell_current@|$(PACKAGE_VERSION)|" \
|
||||||
|
-e "s|[@]url@|$(extensionurl)|" $< > $@
|
||||||
|
|
||||||
|
CLEANFILES = metadata.json
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
DIST_SUBDIRS = $(ALL_EXTENSIONS)
|
||||||
|
|
||||||
|
SUBDIRS = $(ENABLED_EXTENSIONS)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
EXTENSION_ID = alternate-tab
|
||||||
|
|
||||||
|
include ../../extension.mk
|
||||||
|
|
||||||
|
gschemas_in = $(gschemabase).alternate-tab.gschema.xml.in
|
||||||
|
|
||||||
|
@INTLTOOL_XML_NOMERGE_RULE@
|
||||||
|
|
||||||
|
gsettings_SCHEMAS = $(gschemas_in:.xml.in=.xml)
|
||||||
|
|
||||||
|
@GSETTINGS_RULES@
|
||||||
|
|
||||||
|
CLEANFILES += $(gschemas_in:.xml.in=.valid) $(gsettings_SCHEMAS)
|
||||||
|
EXTRA_DIST += $(gschemas_in)
|
||||||
@@ -0,0 +1,627 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
/* most of the code is borrowed from
|
||||||
|
* > js/ui/altTab.js <
|
||||||
|
* of the gnome-shell source code
|
||||||
|
*/
|
||||||
|
|
||||||
|
const AltTab = imports.ui.altTab;
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Gdk = imports.gi.Gdk;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
const ModalDialog = imports.ui.modalDialog;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
const WindowManager = imports.ui.windowManager;
|
||||||
|
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
const N_ = function(e) { return e };
|
||||||
|
|
||||||
|
const POPUP_DELAY_TIMEOUT = 150; // milliseconds
|
||||||
|
|
||||||
|
const SETTINGS_SCHEMA = 'org.gnome.shell.extensions.alternate-tab';
|
||||||
|
const SETTINGS_BEHAVIOUR_KEY = 'behaviour';
|
||||||
|
const SETTINGS_FIRST_TIME_KEY = 'first-time';
|
||||||
|
|
||||||
|
const MODES = {
|
||||||
|
all_thumbnails: function(shellwm, binding, mask, window, backwards) {
|
||||||
|
let tabPopup = new AltTabPopup2();
|
||||||
|
|
||||||
|
if (!tabPopup.show(backwards, binding, mask))
|
||||||
|
tabPopup.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
workspace_icons: function(shellwm, binding, mask, window, backwards) {
|
||||||
|
if (shellwm._workspaceSwitcherPopup != null)
|
||||||
|
shellwm._workspaceSwitcherPopup.actor.hide();
|
||||||
|
|
||||||
|
let tabPopup = new AltTabPopupW();
|
||||||
|
if (!tabPopup.show(backwards, binding, mask))
|
||||||
|
tabPopup.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const MESSAGE = N_("This is the first time you use the Alternate Tab extension. \n\
|
||||||
|
Please choose your preferred behaviour:\n\
|
||||||
|
\n\
|
||||||
|
All & Thumbnails:\n\
|
||||||
|
This mode presents all applications from all workspaces in one selection \n\
|
||||||
|
list. Instead of using the application icon of every window, it uses small \n\
|
||||||
|
thumbnails resembling the window itself. \n\
|
||||||
|
\n\
|
||||||
|
Workspace & Icons:\n\
|
||||||
|
This mode let's you switch between the applications of your current \n\
|
||||||
|
workspace and gives you additionally the option to switch to the last used \n\
|
||||||
|
application of your previous workspace. This is always the last symbol in \n\
|
||||||
|
the list and is segregated by a separator/vertical line if available. \n\
|
||||||
|
Every window is represented by its application icon. \n\
|
||||||
|
\n\
|
||||||
|
If you whish to revert to the default behavior for the Alt-Tab switcher, just\n\
|
||||||
|
disable the extension from extensions.gnome.org or the Advanced Settings application.\
|
||||||
|
");
|
||||||
|
|
||||||
|
function AltTabPopupW() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AltTabPopupW.prototype = {
|
||||||
|
__proto__ : AltTab.AltTabPopup.prototype,
|
||||||
|
|
||||||
|
_windowActivated : function(thumbnailList, n) { },
|
||||||
|
|
||||||
|
show : function(backward, binding, mask) {
|
||||||
|
let appSys = Shell.AppSystem.get_default();
|
||||||
|
let apps = appSys.get_running ();
|
||||||
|
|
||||||
|
if (!apps.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!Main.pushModal(this.actor)) {
|
||||||
|
// Probably someone else has a pointer grab, try again with keyboard only
|
||||||
|
if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._haveModal = true;
|
||||||
|
this._modifierMask = AltTab.primaryModifier(mask);
|
||||||
|
|
||||||
|
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
||||||
|
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
||||||
|
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
|
||||||
|
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
|
||||||
|
|
||||||
|
this._appSwitcher = new WindowSwitcher(apps, this);
|
||||||
|
this.actor.add_actor(this._appSwitcher.actor);
|
||||||
|
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
|
||||||
|
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
|
||||||
|
|
||||||
|
this._appIcons = this._appSwitcher.icons;
|
||||||
|
|
||||||
|
// Need to force an allocation so we can figure out whether we
|
||||||
|
// need to scroll when selecting
|
||||||
|
this.actor.opacity = 0;
|
||||||
|
this.actor.show();
|
||||||
|
this.actor.get_allocation_box();
|
||||||
|
|
||||||
|
// Make the initial selection
|
||||||
|
if (binding == 'switch_group') {
|
||||||
|
//see AltTab.AltTabPopup.show function
|
||||||
|
//cached windows are always of length one, so select first app and the window
|
||||||
|
//the direction doesn't matter, so ignore backward
|
||||||
|
this._select(0, 0);
|
||||||
|
} else if (binding == 'switch_group_backward') {
|
||||||
|
this._select(0, 0);
|
||||||
|
} else if (binding == 'switch_windows_backward') {
|
||||||
|
this._select(this._appIcons.length - 1);
|
||||||
|
} else if (this._appIcons.length == 1) {
|
||||||
|
this._select(0);
|
||||||
|
} else if (backward) {
|
||||||
|
this._select(this._appIcons.length - 1);
|
||||||
|
} else {
|
||||||
|
this._select(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// There's a race condition; if the user released Alt before
|
||||||
|
// we got the grab, then we won't be notified. (See
|
||||||
|
// https://bugzilla.gnome.org/show_bug.cgi?id=596695 for
|
||||||
|
// details.) So we check now. (Have to do this after updating
|
||||||
|
// selection.)
|
||||||
|
let [x, y, mods] = global.get_pointer();
|
||||||
|
if (!(mods & this._modifierMask)) {
|
||||||
|
this._finish();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We delay showing the popup so that fast Alt+Tab users aren't
|
||||||
|
// disturbed by the popup briefly flashing.
|
||||||
|
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
|
||||||
|
Lang.bind(this, function () {
|
||||||
|
this.actor.opacity = 255;
|
||||||
|
this._initialDelayTimeoutId = 0;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
_finish : function() {
|
||||||
|
let app = this._appIcons[this._currentApp];
|
||||||
|
if (!app)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Main.activateWindow(app.cachedWindows[0]);
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function AppIcon(app, window) {
|
||||||
|
this._init(app, window);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppIcon.prototype = {
|
||||||
|
__proto__ : AltTab.AppIcon.prototype,
|
||||||
|
|
||||||
|
_init: function(app, window) {
|
||||||
|
this.app = app;
|
||||||
|
|
||||||
|
this.cachedWindows = [];
|
||||||
|
this.cachedWindows.push(window);
|
||||||
|
|
||||||
|
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
|
||||||
|
vertical: true });
|
||||||
|
this.icon = null;
|
||||||
|
this._iconBin = new St.Bin({ x_fill: true, y_fill: true });
|
||||||
|
|
||||||
|
this.actor.add(this._iconBin, { x_fill: false, y_fill: false } );
|
||||||
|
|
||||||
|
let title = window.get_title();
|
||||||
|
if (title) {
|
||||||
|
this.label = new St.Label({ text: title });
|
||||||
|
let bin = new St.Bin({ x_align: St.Align.MIDDLE });
|
||||||
|
bin.add_actor(this.label);
|
||||||
|
this.actor.add(bin);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.label = new St.Label({ text: this.app.get_name() });
|
||||||
|
this.actor.add(this.label, { x_fill: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function WindowSwitcher(apps, altTabPopup) {
|
||||||
|
this._init(apps, altTabPopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowSwitcher.prototype = {
|
||||||
|
__proto__ : AltTab.AppSwitcher.prototype,
|
||||||
|
|
||||||
|
_init : function(apps, altTabPopup) {
|
||||||
|
AltTab.SwitcherList.prototype._init.call(this, true);
|
||||||
|
|
||||||
|
// Construct the AppIcons, sort by time, add to the popup
|
||||||
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
|
let workspaceIcons = [];
|
||||||
|
let otherIcons = [];
|
||||||
|
for (let i = 0; i < apps.length; i++) {
|
||||||
|
// Cache the window list now; we don't handle dynamic changes here,
|
||||||
|
// and we don't want to be continually retrieving it
|
||||||
|
let windows = apps[i].get_windows();
|
||||||
|
|
||||||
|
for(let j = 0; j < windows.length; j++) {
|
||||||
|
let appIcon = new AppIcon(apps[i], windows[j]);
|
||||||
|
if (this._isWindowOnWorkspace(windows[j], activeWorkspace)) {
|
||||||
|
workspaceIcons.push(appIcon);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
otherIcons.push(appIcon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
workspaceIcons.sort(Lang.bind(this, this._sortAppIcon));
|
||||||
|
otherIcons.sort(Lang.bind(this, this._sortAppIcon));
|
||||||
|
|
||||||
|
if(otherIcons.length > 0) {
|
||||||
|
let mostRecentOtherIcon = otherIcons[0];
|
||||||
|
otherIcons = [];
|
||||||
|
otherIcons.push(mostRecentOtherIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.icons = [];
|
||||||
|
this._arrows = [];
|
||||||
|
for (let i = 0; i < workspaceIcons.length; i++)
|
||||||
|
this._addIcon(workspaceIcons[i]);
|
||||||
|
if (workspaceIcons.length > 0 && otherIcons.length > 0)
|
||||||
|
this.addSeparator();
|
||||||
|
for (let i = 0; i < otherIcons.length; i++)
|
||||||
|
this._addIcon(otherIcons[i]);
|
||||||
|
|
||||||
|
this._curApp = -1;
|
||||||
|
this._iconSize = 0;
|
||||||
|
this._altTabPopup = altTabPopup;
|
||||||
|
this._mouseTimeOutId = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
_isWindowOnWorkspace: function(w, workspace) {
|
||||||
|
if (w.get_workspace() == workspace)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_sortAppIcon : function(appIcon1, appIcon2) {
|
||||||
|
let t1 = appIcon1.cachedWindows[0].get_user_time();
|
||||||
|
let t2 = appIcon2.cachedWindows[0].get_user_time();
|
||||||
|
if (t2 > t1) return 1;
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function AltTabSettingsDialog() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AltTabSettingsDialog.prototype = {
|
||||||
|
__proto__: ModalDialog.ModalDialog.prototype,
|
||||||
|
|
||||||
|
_init : function() {
|
||||||
|
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: null });
|
||||||
|
|
||||||
|
let mainContentBox = new St.BoxLayout({ style_class: 'polkit-dialog-main-layout',
|
||||||
|
vertical: false });
|
||||||
|
this.contentLayout.add(mainContentBox,
|
||||||
|
{ x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
|
||||||
|
let messageBox = new St.BoxLayout({ style_class: 'polkit-dialog-message-layout',
|
||||||
|
vertical: true });
|
||||||
|
mainContentBox.add(messageBox,
|
||||||
|
{ y_align: St.Align.START });
|
||||||
|
|
||||||
|
this._subjectLabel = new St.Label({ style_class: 'polkit-dialog-headline',
|
||||||
|
text: _("Alt Tab Behaviour") });
|
||||||
|
|
||||||
|
messageBox.add(this._subjectLabel,
|
||||||
|
{ y_fill: false,
|
||||||
|
y_align: St.Align.START });
|
||||||
|
|
||||||
|
this._descriptionLabel = new St.Label({ style_class: 'polkit-dialog-description',
|
||||||
|
text: Gettext.gettext(MESSAGE) });
|
||||||
|
|
||||||
|
messageBox.add(this._descriptionLabel,
|
||||||
|
{ y_fill: true,
|
||||||
|
y_align: St.Align.START });
|
||||||
|
|
||||||
|
|
||||||
|
this.setButtons([
|
||||||
|
{
|
||||||
|
label: _("All & Thumbnails"),
|
||||||
|
action: Lang.bind(this, function() {
|
||||||
|
this.setBehaviour('all_thumbnails');
|
||||||
|
this.close();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: _("Workspace & Icons"),
|
||||||
|
action: Lang.bind(this, function() {
|
||||||
|
this.setBehaviour('workspace_icons');
|
||||||
|
this.close();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: _("Cancel"),
|
||||||
|
action: Lang.bind(this, function() {
|
||||||
|
this.close();
|
||||||
|
}),
|
||||||
|
key: Clutter.Escape
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
setBehaviour: function(behaviour) {
|
||||||
|
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
||||||
|
this._settings.set_string(SETTINGS_BEHAVIOUR_KEY, behaviour);
|
||||||
|
this._settings.set_boolean(SETTINGS_FIRST_TIME_KEY, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function AltTabPopup2() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
AltTabPopup2.prototype = {
|
||||||
|
__proto__ : AltTab.AltTabPopup.prototype,
|
||||||
|
|
||||||
|
_init : function() {
|
||||||
|
this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
|
||||||
|
reactive: true });
|
||||||
|
|
||||||
|
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
|
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
|
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
|
|
||||||
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
|
||||||
|
this._haveModal = false;
|
||||||
|
|
||||||
|
this._currentApp = 0;
|
||||||
|
this._currentWindow = -1;
|
||||||
|
this._thumbnailTimeoutId = 0;
|
||||||
|
this._motionTimeoutId = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// Initially disable hover so we ignore the enter-event if
|
||||||
|
// the switcher appears underneath the current pointer location
|
||||||
|
this._disableHover();
|
||||||
|
|
||||||
|
//this.show();
|
||||||
|
Main.uiGroup.add_actor(this.actor);
|
||||||
|
//this._select(0);
|
||||||
|
},
|
||||||
|
|
||||||
|
show : function(backward, binding, mask) {
|
||||||
|
let windows = global.get_window_actors();
|
||||||
|
|
||||||
|
let list = '';
|
||||||
|
let normal_windows= [];
|
||||||
|
let appIcons = [];
|
||||||
|
let appSys = Shell.AppSystem.get_default();
|
||||||
|
let apps = appSys.get_running();
|
||||||
|
|
||||||
|
for (let w = windows.length-1; w >= 0; w--) {
|
||||||
|
let win = windows[w].get_meta_window();
|
||||||
|
normal_windows.push(win);
|
||||||
|
}
|
||||||
|
normal_windows.sort(Lang.bind(this, this._sortWindows));
|
||||||
|
|
||||||
|
let win_on_top = normal_windows.shift();
|
||||||
|
normal_windows.push(win_on_top);
|
||||||
|
windows = normal_windows;
|
||||||
|
for (let w = 0; w < windows.length; w++) {
|
||||||
|
let win = windows[w];
|
||||||
|
|
||||||
|
let ap1 = null;
|
||||||
|
for (let i = 0;i < apps.length; i++) {
|
||||||
|
let app_wins = apps[i].get_windows();
|
||||||
|
for (let j = 0;j < app_wins.length; j++) {
|
||||||
|
if (app_wins[j] == win)
|
||||||
|
ap1 = new AltTab.AppIcon(apps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ap1 != null) {
|
||||||
|
ap1.cachedWindows = [win];
|
||||||
|
appIcons.push(ap1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!windows.length) {
|
||||||
|
this.destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Main.pushModal(this.actor)) {
|
||||||
|
// Probably someone else has a pointer grab, try again with keyboard only
|
||||||
|
if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._haveModal = true;
|
||||||
|
this._modifierMask = AltTab.primaryModifier(mask);
|
||||||
|
|
||||||
|
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
|
||||||
|
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
|
||||||
|
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
|
||||||
|
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
|
||||||
|
|
||||||
|
this._appSwitcher = new WindowList(windows);
|
||||||
|
this._appSwitcher._altTabPopup=this;
|
||||||
|
this.actor.add_actor(this._appSwitcher.actor);
|
||||||
|
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
|
||||||
|
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
|
||||||
|
|
||||||
|
this._appIcons = appIcons;
|
||||||
|
|
||||||
|
// make the initial selection
|
||||||
|
if (backward)
|
||||||
|
this._select(windows.length - 2);
|
||||||
|
else
|
||||||
|
this._select(0);
|
||||||
|
|
||||||
|
this.actor.opacity = 0;
|
||||||
|
this.actor.show();
|
||||||
|
|
||||||
|
// There's a race condition; if the user released Alt before
|
||||||
|
// we got the grab, then we won't be notified. (See
|
||||||
|
// https://bugzilla.gnome.org/show_bug.cgi?id=596695 for
|
||||||
|
// details.) So we check now. (Have to do this after updating
|
||||||
|
// selection.)
|
||||||
|
let [x, y, mods] = global.get_pointer();
|
||||||
|
if (!(mods & this._modifierMask)) {
|
||||||
|
this._finish();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We delay showing the popup so that fast Alt+Tab users aren't
|
||||||
|
// disturbed by the popup briefly flashing.
|
||||||
|
this._initialDelayTimeoutId = Mainloop.timeout_add(AltTab.POPUP_DELAY_TIMEOUT,
|
||||||
|
Lang.bind(this, function () {
|
||||||
|
this.actor.opacity = 255;
|
||||||
|
this._initialDelayTimeoutId = 0;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
_keyPressEvent : function(actor, event) {
|
||||||
|
let keysym = event.get_key_symbol();
|
||||||
|
let shift = (Shell.get_event_state(event) & Clutter.ModifierType.SHIFT_MASK);
|
||||||
|
// X allows servers to represent Shift+Tab in two different ways
|
||||||
|
if (shift && keysym == Clutter.Tab)
|
||||||
|
keysym = Clutter.ISO_Left_Tab;
|
||||||
|
|
||||||
|
this._disableHover();
|
||||||
|
|
||||||
|
if (keysym == Clutter.grave)
|
||||||
|
this._select(this._currentApp, this._nextWindow());
|
||||||
|
else if (keysym == Clutter.asciitilde)
|
||||||
|
this._select(this._currentApp, this._previousWindow());
|
||||||
|
else if (keysym == Clutter.Escape)
|
||||||
|
this.destroy();
|
||||||
|
else if (this._thumbnailsFocused) {
|
||||||
|
if (keysym == Clutter.Tab) {
|
||||||
|
if (this._currentWindow == this._appIcons[this._currentApp].cachedWindows.length - 1)
|
||||||
|
this._select(this._nextApp());
|
||||||
|
else
|
||||||
|
this._select(this._currentApp, this._nextWindow());
|
||||||
|
} else if (keysym == Clutter.ISO_Left_Tab) {
|
||||||
|
if (this._currentWindow == 0 || this._currentWindow == -1)
|
||||||
|
this._select(this._previousApp());
|
||||||
|
else
|
||||||
|
this._select(this._currentApp, this._previousWindow());
|
||||||
|
} else if (keysym == Clutter.Left)
|
||||||
|
this._select(this._currentApp, this._previousWindow());
|
||||||
|
else if (keysym == Clutter.Right)
|
||||||
|
this._select(this._currentApp, this._nextWindow());
|
||||||
|
else if (keysym == Clutter.Up)
|
||||||
|
this._select(this._currentApp, null, true);
|
||||||
|
} else {
|
||||||
|
if (keysym == Clutter.Tab)
|
||||||
|
this._select(this._nextApp());
|
||||||
|
else if (keysym == Clutter.ISO_Left_Tab)
|
||||||
|
this._select(this._previousApp());
|
||||||
|
else if (keysym == Clutter.Left)
|
||||||
|
this._select(this._previousApp());
|
||||||
|
else if (keysym == Clutter.Right)
|
||||||
|
this._select(this._nextApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
*/
|
||||||
|
|
||||||
|
_sortWindows : function(win1,win2) {
|
||||||
|
let t1 = win1.get_user_time();
|
||||||
|
let t2 = win2.get_user_time();
|
||||||
|
if (t2 > t1) return 1;
|
||||||
|
else return -1;
|
||||||
|
},
|
||||||
|
|
||||||
|
_appActivated : function(thumbnailList, n) {
|
||||||
|
let appIcon = this._appIcons[this._currentApp];
|
||||||
|
Main.activateWindow(appIcon.cachedWindows[0]);
|
||||||
|
this.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
_finish : function() {
|
||||||
|
let app = this._appIcons[this._currentApp];
|
||||||
|
Main.activateWindow(app.cachedWindows[0]);
|
||||||
|
this.destroy();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function WindowList(windows) {
|
||||||
|
this._init(windows);
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowList.prototype = {
|
||||||
|
__proto__ : AltTab.SwitcherList.prototype,
|
||||||
|
|
||||||
|
_init : function(windows) {
|
||||||
|
AltTab.SwitcherList.prototype._init.call(this, true);
|
||||||
|
|
||||||
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
|
this._labels = new Array();
|
||||||
|
this._thumbnailBins = new Array();
|
||||||
|
this._clones = new Array();
|
||||||
|
this._windows = windows;
|
||||||
|
this._arrows = new Array();
|
||||||
|
this.icons = new Array();
|
||||||
|
for (let w = 0; w < windows.length; w++) {
|
||||||
|
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
|
||||||
|
arrow.connect('repaint', Lang.bind(this, function (area) {
|
||||||
|
Shell.draw_box_pointer(area, Shell.PointerDirection.DOWN);
|
||||||
|
}));
|
||||||
|
this._list.add_actor(arrow);
|
||||||
|
this._arrows.push(arrow);
|
||||||
|
|
||||||
|
arrow.hide();
|
||||||
|
|
||||||
|
let win=windows[w];
|
||||||
|
|
||||||
|
let appSys = Shell.AppSystem.get_default();
|
||||||
|
let apps = appSys.get_running();
|
||||||
|
let ap1 = null;
|
||||||
|
for (let i = 0; i < apps.length; i++) {
|
||||||
|
let app_wins = apps[i].get_windows();
|
||||||
|
for (let j = 0; j < app_wins.length; j++) {
|
||||||
|
if (app_wins[j] == win) {
|
||||||
|
ap1 = new AltTab.AppIcon(apps[i]);
|
||||||
|
let mutterWindow = win.get_compositor_private();
|
||||||
|
let windowTexture = mutterWindow.get_texture ();
|
||||||
|
let [width, height] = windowTexture.get_size();
|
||||||
|
let scale = Math.min(1.0, 128 / width, 128 / height);
|
||||||
|
|
||||||
|
let clone = new Clutter.Clone ({ source: windowTexture, reactive: true, width: width * scale, height: height * scale });
|
||||||
|
ap1.icon = ap1.app.create_icon_texture(128);
|
||||||
|
ap1._iconBin.set_size(128,128);
|
||||||
|
ap1._iconBin.child = clone;
|
||||||
|
|
||||||
|
ap1.label.text = win.get_title();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ap1 != null) {
|
||||||
|
ap1.cachedWindows = [win];
|
||||||
|
this.addItem(ap1.actor, ap1.label);
|
||||||
|
this.icons.push(ap1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addSeparator: function () {
|
||||||
|
this._separator=null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(metadata) {
|
||||||
|
imports.gettext.bindtextdomain('gnome-shell-extensions', GLib.build_filenamev([metadata.path, 'locale']));
|
||||||
|
}
|
||||||
|
|
||||||
|
function doAltTab(shellwm, binding, mask, window, backwards) {
|
||||||
|
let settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
||||||
|
|
||||||
|
|
||||||
|
if(settings.get_boolean(SETTINGS_FIRST_TIME_KEY)) {
|
||||||
|
new AltTabSettingsDialog().open();
|
||||||
|
} else {
|
||||||
|
let behaviour = settings.get_string(SETTINGS_BEHAVIOUR_KEY);
|
||||||
|
if(behaviour in MODES) {
|
||||||
|
MODES[behaviour](shellwm, binding, mask, window, backwards);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable() {
|
||||||
|
Main.wm.setKeybindingHandler('switch-windows', doAltTab);
|
||||||
|
Main.wm.setKeybindingHandler('switch-group', doAltTab);
|
||||||
|
Main.wm.setKeybindingHandler('switch-windows-backward', doAltTab);
|
||||||
|
Main.wm.setKeybindingHandler('switch-group-backward', doAltTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
Main.wm.setKeybindingHandler('switch-windows', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
|
||||||
|
Main.wm.setKeybindingHandler('switch-group', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
|
||||||
|
Main.wm.setKeybindingHandler('switch-windows-backward', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
|
||||||
|
Main.wm.setKeybindingHandler('switch-group-backward', Lang.bind(Main.wm, Main.wm._startAppSwitcher));
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"uuid": "@uuid@",
|
||||||
|
"name": "AlternateTab",
|
||||||
|
"description": "A replacement for Alt-Tab, allows to cycle between windows and does not group by application",
|
||||||
|
"original-authors": [ "jw@bargsten.org", "thomas.bouffon@gmail.com" ],
|
||||||
|
"shell-version": [ "@shell_current@", "3.2" ],
|
||||||
|
"url": "@url@"
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<schemalist gettext-domain="gnome-shell-extensions">
|
||||||
|
<enum id="org.gnome.shell.extensions.alternate-tab.BehaviourMode">
|
||||||
|
<value value="1" nick="all_thumbnails"/>
|
||||||
|
<value value="2" nick="workspace_icons"/>
|
||||||
|
</enum>
|
||||||
|
<schema id="org.gnome.shell.extensions.alternate-tab" path="/org/gnome/shell/extensions/alternate-tab/">
|
||||||
|
<key name="behaviour" enum="org.gnome.shell.extensions.alternate-tab.BehaviourMode">
|
||||||
|
<default>'all_thumbnails'</default>
|
||||||
|
<_summary>The alt tab behaviour.</_summary>
|
||||||
|
<_description>Sets the Alt-Tab behaviour. Possible values are: native, all_thumbnails and workspace_icons.</_description>
|
||||||
|
</key>
|
||||||
|
<key type="b" name="first-time">
|
||||||
|
<default>true</default>
|
||||||
|
<_summary>Indicates if Alternate Tab is newly installed</_summary>
|
||||||
|
<_description>Ask the user for a default behaviour if true.</_description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/* This extensions requires no special styling */
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
EXTENSION_ID = alternative-status-menu
|
||||||
|
|
||||||
|
include ../../extension.mk
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/* -*- mode: js2 - indent-tabs-mode: nil - js2-basic-offset: 4 -*- */
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
|
const GnomeSession = imports.misc.gnomeSession;
|
||||||
|
const UserMenu = imports.ui.userMenu;
|
||||||
|
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
function updateSuspend(object, pspec, item) {
|
||||||
|
item.actor.visible = object.get_can_suspend();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateHibernate(object, pspec, item) {
|
||||||
|
item.actor.visible = object.get_can_hibernate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSuspendActivate(item) {
|
||||||
|
Main.overview.hide();
|
||||||
|
|
||||||
|
this._screenSaverProxy.LockRemote(Lang.bind(this, function() {
|
||||||
|
this._upClient.suspend_sync(null);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onHibernateActivate(item) {
|
||||||
|
Main.overview.hide();
|
||||||
|
|
||||||
|
this._screenSaverProxy.LockRemote(Lang.bind(this, function() {
|
||||||
|
this._upClient.hibernate_sync(null);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSubMenu() {
|
||||||
|
let item;
|
||||||
|
|
||||||
|
item = new UserMenu.IMStatusChooserItem();
|
||||||
|
item.connect('activate', Lang.bind(this, this._onMyAccountActivate));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
|
||||||
|
item.connect('activate', Lang.bind(this, this._updatePresenceStatus));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
this._notificationsSwitch = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Online Accounts"));
|
||||||
|
item.connect('activate', Lang.bind(this, this._onOnlineAccountsActivate));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("System Settings"));
|
||||||
|
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Lock Screen"));
|
||||||
|
item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
this._lockScreenItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Switch User"));
|
||||||
|
item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
this._loginScreenItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Log Out..."));
|
||||||
|
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
this._logoutItem = item;
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Suspend"));
|
||||||
|
item.connect('activate', Lang.bind(this, onSuspendActivate));
|
||||||
|
this._upClient.connect('notify::can-suspend', Lang.bind(this, updateSuspend, item));
|
||||||
|
updateSuspend(this._upClient, null, item);
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Hibernate"));
|
||||||
|
item.connect('activate', Lang.bind(this, onHibernateActivate));
|
||||||
|
this._upClient.connect('notify::can-hibernate', Lang.bind(this, updateHibernate, item));
|
||||||
|
updateHibernate(this._upClient, null, item);
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
|
||||||
|
item = new PopupMenu.PopupMenuItem(_("Power Off..."));
|
||||||
|
item.connect('activate', Lang.bind(this, function() {
|
||||||
|
this._session.ShutdownRemote();
|
||||||
|
}));
|
||||||
|
this.menu.addMenuItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put your extension initialization code here
|
||||||
|
function init(metadata) {
|
||||||
|
imports.gettext.bindtextdomain('gnome-shell-extensions', GLib.build_filenamev([metadata.path, 'locale']));
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset(statusMenu) {
|
||||||
|
statusMenu._updateSwitchUser();
|
||||||
|
statusMenu._updateLogout();
|
||||||
|
statusMenu._updateLockScreen();
|
||||||
|
|
||||||
|
statusMenu._presence.getStatus(Lang.bind(statusMenu, statusMenu._updateSwitch));
|
||||||
|
|
||||||
|
// HACK! Obtain the IMStatusChooserItem and force a _updateUser
|
||||||
|
statusMenu.menu._getMenuItems()[0]._updateUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable() {
|
||||||
|
let statusMenu = Main.panel._statusArea.userMenu;
|
||||||
|
statusMenu.menu.removeAll();
|
||||||
|
createSubMenu.call(statusMenu);
|
||||||
|
reset(statusMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
// not guarranteed to work, if more extensions operate in the same place
|
||||||
|
let statusMenu = Main.panel._statusArea.userMenu;
|
||||||
|
statusMenu.menu.removeAll();
|
||||||
|
statusMenu._createSubMenu();
|
||||||
|
reset(statusMenu);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"uuid": "@uuid@",
|
||||||
|
"name": "Alternative Status Menu",
|
||||||
|
"description": "Replaces GNOME Shell Status Menu with one showing Suspend/Hibernate and Power Off as separate items",
|
||||||
|
"shell-version": [ "@shell_current@", "3.2" ],
|
||||||
|
"url": "@url@"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.popup-alternating-menu-item:alternate {
|
||||||
|
font-weight: normal !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
EXTENSION_ID = apps-menu
|
||||||
|
|
||||||
|
include ../../extension.mk
|
||||||
@@ -1,698 +1,111 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
/* exported init enable disable */
|
|
||||||
|
|
||||||
const {
|
const GMenu = imports.gi.GMenu;
|
||||||
Atk, Clutter, Gio, GLib, GMenu, GObject, Gtk, Meta, Shell, St,
|
const Lang = imports.lang;
|
||||||
} = imports.gi;
|
const Shell = imports.gi.Shell;
|
||||||
const {EventEmitter} = imports.misc.signals;
|
const St = imports.gi.St;
|
||||||
|
|
||||||
const DND = imports.ui.dnd;
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const PanelMenu = imports.ui.panelMenu;
|
const PanelMenu = imports.ui.panelMenu;
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
|
|
||||||
const _ = ExtensionUtils.gettext;
|
const ICON_SIZE = 28;
|
||||||
|
let appsys = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
const appSys = Shell.AppSystem.get_default();
|
function AppMenuItem() {
|
||||||
|
this._init.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
const APPLICATION_ICON_SIZE = 32;
|
AppMenuItem.prototype = {
|
||||||
const HORIZ_FACTOR = 5;
|
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
|
||||||
const MENU_HEIGHT_OFFSET = 132;
|
|
||||||
const NAVIGATION_REGION_OVERSHOOT = 50;
|
|
||||||
|
|
||||||
Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish');
|
_init: function (app, params) {
|
||||||
Gio._promisify(Gio._LocalFilePrototype, 'set_attributes_async', 'set_attributes_finish');
|
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
|
||||||
|
|
||||||
class ApplicationMenuItem extends PopupMenu.PopupBaseMenuItem {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(button, app) {
|
|
||||||
super();
|
|
||||||
this._app = app;
|
this._app = app;
|
||||||
this._button = button;
|
this.label = new St.Label({ text: app.get_name() });
|
||||||
|
this.addActor(this.label);
|
||||||
|
this._icon = app.create_icon_texture(ICON_SIZE);
|
||||||
|
this.addActor(this._icon, { expand: false });
|
||||||
|
},
|
||||||
|
|
||||||
this._iconBin = new St.Bin();
|
activate: function (event) {
|
||||||
this.add_child(this._iconBin);
|
this._app.activate_full(-1, event.get_time());
|
||||||
|
|
||||||
let appLabel = new St.Label({
|
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this, event);
|
||||||
text: app.get_name(),
|
|
||||||
y_expand: true,
|
|
||||||
y_align: Clutter.ActorAlign.CENTER,
|
|
||||||
});
|
|
||||||
this.add_child(appLabel);
|
|
||||||
this.label_actor = appLabel;
|
|
||||||
|
|
||||||
let textureCache = St.TextureCache.get_default();
|
|
||||||
let iconThemeChangedId = textureCache.connect('icon-theme-changed',
|
|
||||||
this._updateIcon.bind(this));
|
|
||||||
this.connect('destroy', () => {
|
|
||||||
textureCache.disconnect(iconThemeChangedId);
|
|
||||||
});
|
|
||||||
this._updateIcon();
|
|
||||||
|
|
||||||
this._delegate = this;
|
|
||||||
let draggable = DND.makeDraggable(this);
|
|
||||||
|
|
||||||
let maybeStartDrag = draggable._maybeStartDrag;
|
|
||||||
draggable._maybeStartDrag = event => {
|
|
||||||
if (this._dragEnabled)
|
|
||||||
return maybeStartDrag.call(draggable, event);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activate(event) {
|
};
|
||||||
this._app.open_new_window(-1);
|
|
||||||
this._button.selectCategory(null);
|
|
||||||
this._button.menu.toggle();
|
|
||||||
super.activate(event);
|
|
||||||
|
|
||||||
Main.overview.hide();
|
function ApplicationsButton() {
|
||||||
}
|
this._init();
|
||||||
|
|
||||||
setActive(active, params) {
|
|
||||||
if (active)
|
|
||||||
this._button.scrollToButton(this);
|
|
||||||
super.setActive(active, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
setDragEnabled(enabled) {
|
|
||||||
this._dragEnabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDragActor() {
|
|
||||||
return this._app.create_icon_texture(APPLICATION_ICON_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
getDragActorSource() {
|
|
||||||
return this._iconBin;
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateIcon() {
|
|
||||||
let icon = this.getDragActor();
|
|
||||||
icon.style_class = 'icon-dropshadow';
|
|
||||||
this._iconBin.set_child(icon);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem {
|
ApplicationsButton.prototype = {
|
||||||
static {
|
__proto__: PanelMenu.SystemStatusButton.prototype,
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(button, category) {
|
_init: function() {
|
||||||
super();
|
PanelMenu.SystemStatusButton.prototype._init.call(this, 'start-here');
|
||||||
this._category = category;
|
|
||||||
this._button = button;
|
|
||||||
|
|
||||||
this._oldX = -1;
|
|
||||||
this._oldY = -1;
|
|
||||||
|
|
||||||
let name;
|
|
||||||
if (this._category)
|
|
||||||
name = this._category.get_name();
|
|
||||||
else
|
|
||||||
name = _('Favorites');
|
|
||||||
|
|
||||||
this.add_child(new St.Label({text: name}));
|
|
||||||
this.connect('motion-event', this._onMotionEvent.bind(this));
|
|
||||||
this.connect('notify::active', this._onActiveChanged.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
activate(event) {
|
|
||||||
this._button.selectCategory(this._category);
|
|
||||||
this._button.scrollToCatButton(this);
|
|
||||||
super.activate(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isNavigatingSubmenu([x, y]) {
|
|
||||||
let [posX, posY] = this.get_transformed_position();
|
|
||||||
|
|
||||||
if (this._oldX === -1) {
|
|
||||||
this._oldX = x;
|
|
||||||
this._oldY = y;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let deltaX = Math.abs(x - this._oldX);
|
|
||||||
let deltaY = Math.abs(y - this._oldY);
|
|
||||||
|
|
||||||
this._oldX = x;
|
|
||||||
this._oldY = y;
|
|
||||||
|
|
||||||
// If it lies outside the x-coordinates then it is definitely outside.
|
|
||||||
if (posX > x || posX + this.width < x)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If it lies inside the menu item then it is definitely inside.
|
|
||||||
if (posY <= y && posY + this.height >= y)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// We want the keep-up triangle only if the movement is more
|
|
||||||
// horizontal than vertical.
|
|
||||||
if (deltaX * HORIZ_FACTOR < deltaY)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the point lies inside triangle ABC, and a similar
|
|
||||||
// triangle on the other side of the menu item.
|
|
||||||
//
|
|
||||||
// +---------------------+
|
|
||||||
// | menu item |
|
|
||||||
// A +---------------------+ C
|
|
||||||
// P |
|
|
||||||
// B
|
|
||||||
|
|
||||||
// Ensure that the point P always lies below line AC so that we can
|
|
||||||
// only check for triangle ABC.
|
|
||||||
if (posY > y) {
|
|
||||||
let offset = posY - y;
|
|
||||||
y = posY + this.height + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that A is (0, 0).
|
|
||||||
x -= posX;
|
|
||||||
y -= posY + this.height;
|
|
||||||
|
|
||||||
// Check which side of line AB the point P lies on by taking the
|
|
||||||
// cross-product of AB and AP. See:
|
|
||||||
// http://stackoverflow.com/questions/3461453/determine-which-side-of-a-line-a-point-lies
|
|
||||||
if (this.width * y - NAVIGATION_REGION_OVERSHOOT * x <= 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMotionEvent(actor, event) {
|
|
||||||
if (!this._grab) {
|
|
||||||
this._oldX = -1;
|
|
||||||
this._oldY = -1;
|
|
||||||
const grab = global.stage.grab(this);
|
|
||||||
if (grab.get_seat_state() !== Clutter.GrabState.NONE)
|
|
||||||
this._grab = grab;
|
|
||||||
else
|
|
||||||
grab.dismiss();
|
|
||||||
}
|
|
||||||
this.hover = true;
|
|
||||||
|
|
||||||
if (this._isNavigatingSubmenu(event.get_coords()))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
this._oldX = -1;
|
|
||||||
this._oldY = -1;
|
|
||||||
this.hover = false;
|
|
||||||
this._grab?.dismiss();
|
|
||||||
delete this._grab;
|
|
||||||
|
|
||||||
let source = event.get_source();
|
|
||||||
if (source instanceof St.Widget)
|
|
||||||
source.sync_hover();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onActiveChanged() {
|
|
||||||
if (!this.active)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._button.selectCategory(this._category);
|
|
||||||
this._button.scrollToCatButton(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApplicationsMenu extends PopupMenu.PopupMenu {
|
|
||||||
constructor(sourceActor, arrowAlignment, arrowSide, button) {
|
|
||||||
super(sourceActor, arrowAlignment, arrowSide);
|
|
||||||
this._button = button;
|
|
||||||
}
|
|
||||||
|
|
||||||
isEmpty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
if (this.isOpen)
|
|
||||||
this._button.selectCategory(null);
|
|
||||||
super.toggle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DesktopTarget extends EventEmitter {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this._desktop = null;
|
|
||||||
this._desktopDestroyedId = 0;
|
|
||||||
|
|
||||||
this._windowAddedId =
|
|
||||||
global.window_group.connect('actor-added',
|
|
||||||
this._onWindowAdded.bind(this));
|
|
||||||
|
|
||||||
global.get_window_actors().forEach(a => {
|
|
||||||
this._onWindowAdded(a.get_parent(), a);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasDesktop() {
|
|
||||||
return this._desktop !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onWindowAdded(group, actor) {
|
|
||||||
if (!(actor instanceof Meta.WindowActor))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (actor.meta_window.get_window_type() === Meta.WindowType.DESKTOP)
|
|
||||||
this._setDesktop(actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
_setDesktop(desktop) {
|
|
||||||
if (this._desktop) {
|
|
||||||
this._desktop.disconnect(this._desktopDestroyedId);
|
|
||||||
this._desktopDestroyedId = 0;
|
|
||||||
|
|
||||||
delete this._desktop._delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._desktop = desktop;
|
|
||||||
this.emit('desktop-changed');
|
|
||||||
|
|
||||||
if (this._desktop) {
|
|
||||||
this._desktopDestroyedId = this._desktop.connect('destroy', () => {
|
|
||||||
this._setDesktop(null);
|
|
||||||
});
|
|
||||||
this._desktop._delegate = this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_getSourceAppInfo(source) {
|
|
||||||
if (!(source instanceof ApplicationMenuItem))
|
|
||||||
return null;
|
|
||||||
return source._app.app_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
async _markTrusted(file) {
|
|
||||||
let modeAttr = Gio.FILE_ATTRIBUTE_UNIX_MODE;
|
|
||||||
let trustedAttr = 'metadata::trusted';
|
|
||||||
let queryFlags = Gio.FileQueryInfoFlags.NONE;
|
|
||||||
let ioPriority = GLib.PRIORITY_DEFAULT;
|
|
||||||
|
|
||||||
try {
|
|
||||||
let info = await file.query_info_async(modeAttr, queryFlags, ioPriority, null);
|
|
||||||
|
|
||||||
let mode = info.get_attribute_uint32(modeAttr) | 0o100;
|
|
||||||
info.set_attribute_uint32(modeAttr, mode);
|
|
||||||
info.set_attribute_string(trustedAttr, 'yes');
|
|
||||||
await file.set_attributes_async(info, queryFlags, ioPriority, null);
|
|
||||||
|
|
||||||
// Hack: force nautilus to reload file info
|
|
||||||
info = new Gio.FileInfo();
|
|
||||||
info.set_attribute_uint64(
|
|
||||||
Gio.FILE_ATTRIBUTE_TIME_ACCESS, GLib.get_real_time());
|
|
||||||
try {
|
|
||||||
await file.set_attributes_async(info, queryFlags, ioPriority, null);
|
|
||||||
} catch (e) {
|
|
||||||
log(`Failed to update access time: ${e.message}`);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log(`Failed to mark file as trusted: ${e.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
|
||||||
if (this._windowAddedId)
|
|
||||||
global.window_group.disconnect(this._windowAddedId);
|
|
||||||
this._windowAddedId = 0;
|
|
||||||
|
|
||||||
this._setDesktop(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleDragOver(source, _actor, _x, _y, _time) {
|
|
||||||
let appInfo = this._getSourceAppInfo(source);
|
|
||||||
if (!appInfo)
|
|
||||||
return DND.DragMotionResult.CONTINUE;
|
|
||||||
|
|
||||||
return DND.DragMotionResult.COPY_DROP;
|
|
||||||
}
|
|
||||||
|
|
||||||
acceptDrop(source, _actor, _x, _y, _time) {
|
|
||||||
let appInfo = this._getSourceAppInfo(source);
|
|
||||||
if (!appInfo)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
this.emit('app-dropped');
|
|
||||||
|
|
||||||
let desktop = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
|
|
||||||
|
|
||||||
let src = Gio.File.new_for_path(appInfo.get_filename());
|
|
||||||
let dst = Gio.File.new_for_path(GLib.build_filenamev([desktop, src.get_basename()]));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// copy_async() isn't introspectable :-(
|
|
||||||
src.copy(dst, Gio.FileCopyFlags.OVERWRITE, null, null);
|
|
||||||
this._markTrusted(dst);
|
|
||||||
} catch (e) {
|
|
||||||
log(`Failed to copy to desktop: ${e.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApplicationsButton extends PanelMenu.Button {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super(1.0, null, false);
|
|
||||||
|
|
||||||
this.setMenu(new ApplicationsMenu(this, 1.0, St.Side.TOP, this));
|
|
||||||
Main.panel.menuManager.addMenu(this.menu);
|
|
||||||
|
|
||||||
// At this moment applications menu is not keyboard navigable at
|
|
||||||
// all (so not accessible), so it doesn't make sense to set as
|
|
||||||
// role ATK_ROLE_MENU like other elements of the panel.
|
|
||||||
this.accessible_role = Atk.Role.LABEL;
|
|
||||||
|
|
||||||
this._label = new St.Label({
|
|
||||||
text: _('Applications'),
|
|
||||||
y_expand: true,
|
|
||||||
y_align: Clutter.ActorAlign.CENTER,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.add_actor(this._label);
|
|
||||||
this.name = 'panelApplications';
|
|
||||||
this.label_actor = this._label;
|
|
||||||
|
|
||||||
this._showingId = Main.overview.connect('showing', () => {
|
|
||||||
this.add_accessible_state(Atk.StateType.CHECKED);
|
|
||||||
});
|
|
||||||
this._hidingId = Main.overview.connect('hiding', () => {
|
|
||||||
this.remove_accessible_state(Atk.StateType.CHECKED);
|
|
||||||
});
|
|
||||||
Main.wm.addKeybinding(
|
|
||||||
'apps-menu-toggle-menu',
|
|
||||||
ExtensionUtils.getSettings(),
|
|
||||||
Meta.KeyBindingFlags.IGNORE_AUTOREPEAT,
|
|
||||||
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
|
|
||||||
() => this.menu.toggle());
|
|
||||||
|
|
||||||
this._desktopTarget = new DesktopTarget();
|
|
||||||
this._desktopTarget.connect('app-dropped', () => {
|
|
||||||
this.menu.close();
|
|
||||||
});
|
|
||||||
this._desktopTarget.connect('desktop-changed', () => {
|
|
||||||
this._applicationsButtons.forEach(item => {
|
|
||||||
item.setDragEnabled(this._desktopTarget.hasDesktop);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this._tree = new GMenu.Tree({menu_basename: 'applications.menu'});
|
|
||||||
this._treeChangedId = this._tree.connect('changed',
|
|
||||||
this._onTreeChanged.bind(this));
|
|
||||||
|
|
||||||
this._applicationsButtons = new Map();
|
|
||||||
this.reloadFlag = false;
|
|
||||||
this._createLayout();
|
|
||||||
this._display();
|
this._display();
|
||||||
this._installedChangedId = appSys.connect('installed-changed',
|
appsys.connect('installed-changed', Lang.bind(this, this.reDisplay));
|
||||||
this._onTreeChanged.bind(this));
|
},
|
||||||
}
|
|
||||||
|
|
||||||
_onTreeChanged() {
|
reDisplay : function() {
|
||||||
if (this.menu.isOpen) {
|
this._clearAll();
|
||||||
this._redisplay();
|
|
||||||
this.mainBox.show();
|
|
||||||
} else {
|
|
||||||
this.reloadFlag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_createVertSeparator() {
|
|
||||||
let separator = new St.DrawingArea({
|
|
||||||
style_class: 'calendar-vertical-separator',
|
|
||||||
pseudo_class: 'highlighted',
|
|
||||||
});
|
|
||||||
separator.connect('repaint', this._onVertSepRepaint.bind(this));
|
|
||||||
return separator;
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDestroy() {
|
|
||||||
super._onDestroy();
|
|
||||||
|
|
||||||
Main.overview.disconnect(this._showingId);
|
|
||||||
Main.overview.disconnect(this._hidingId);
|
|
||||||
appSys.disconnect(this._installedChangedId);
|
|
||||||
this._tree.disconnect(this._treeChangedId);
|
|
||||||
this._tree = null;
|
|
||||||
|
|
||||||
Main.wm.removeKeybinding('apps-menu-toggle-menu');
|
|
||||||
|
|
||||||
this._desktopTarget.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMenuKeyPress(actor, event) {
|
|
||||||
let symbol = event.get_key_symbol();
|
|
||||||
if (symbol === Clutter.KEY_Left || symbol === Clutter.KEY_Right) {
|
|
||||||
let direction = symbol === Clutter.KEY_Left
|
|
||||||
? Gtk.DirectionType.LEFT : Gtk.DirectionType.RIGHT;
|
|
||||||
if (this.menu.actor.navigate_focus(global.stage.key_focus, direction, false))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super._onMenuKeyPress(actor, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onVertSepRepaint(area) {
|
|
||||||
let cr = area.get_context();
|
|
||||||
let themeNode = area.get_theme_node();
|
|
||||||
let [width, height] = area.get_surface_size();
|
|
||||||
let stippleColor = themeNode.get_color('-stipple-color');
|
|
||||||
let stippleWidth = themeNode.get_length('-stipple-width');
|
|
||||||
let x = Math.floor(width / 2) + 0.5;
|
|
||||||
cr.moveTo(x, 0);
|
|
||||||
cr.lineTo(x, height);
|
|
||||||
Clutter.cairo_set_source_color(cr, stippleColor);
|
|
||||||
cr.setDash([1, 3], 1); // Hard-code for now
|
|
||||||
cr.setLineWidth(stippleWidth);
|
|
||||||
cr.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onOpenStateChanged(menu, open) {
|
|
||||||
if (open) {
|
|
||||||
if (this.reloadFlag) {
|
|
||||||
this._redisplay();
|
|
||||||
this.reloadFlag = false;
|
|
||||||
}
|
|
||||||
this.mainBox.show();
|
|
||||||
}
|
|
||||||
super._onOpenStateChanged(menu, open);
|
|
||||||
}
|
|
||||||
|
|
||||||
_redisplay() {
|
|
||||||
this.applicationsBox.destroy_all_children();
|
|
||||||
this.categoriesBox.destroy_all_children();
|
|
||||||
this._display();
|
this._display();
|
||||||
}
|
},
|
||||||
|
|
||||||
_loadCategory(categoryId, dir) {
|
_clearAll : function() {
|
||||||
let iter = dir.iter();
|
this.menu.removeAll();
|
||||||
let nextType;
|
},
|
||||||
while ((nextType = iter.next()) !== GMenu.TreeItemType.INVALID) {
|
|
||||||
if (nextType === GMenu.TreeItemType.ENTRY) {
|
// Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
|
||||||
let entry = iter.get_entry();
|
// (taken from js/ui/appDisplay.js in core shell)
|
||||||
let id;
|
_loadCategory: function(dir, menu) {
|
||||||
try {
|
var iter = dir.iter();
|
||||||
id = entry.get_desktop_file_id(); // catch non-UTF8 filenames
|
var nextType;
|
||||||
} catch (e) {
|
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
||||||
continue;
|
if (nextType == GMenu.TreeItemType.ENTRY) {
|
||||||
}
|
var entry = iter.get_entry();
|
||||||
let app = appSys.lookup_app(id);
|
var app = appsys.lookup_app_by_tree_entry(entry);
|
||||||
if (!app)
|
if (!entry.get_app_info().get_nodisplay())
|
||||||
app = new Shell.App({app_info: entry.get_app_info()});
|
menu.addMenuItem(new AppMenuItem(app));
|
||||||
if (app.get_app_info().should_show())
|
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||||
this.applicationsByCategory[categoryId].push(app);
|
this._loadCategory(iter.get_directory(), menu);
|
||||||
} else if (nextType === GMenu.TreeItemType.SEPARATOR) {
|
|
||||||
this.applicationsByCategory[categoryId].push('separator');
|
|
||||||
} else if (nextType === GMenu.TreeItemType.DIRECTORY) {
|
|
||||||
let subdir = iter.get_directory();
|
|
||||||
if (!subdir.get_is_nodisplay())
|
|
||||||
this._loadCategory(categoryId, subdir);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
scrollToButton(button) {
|
_display : function() {
|
||||||
let appsScrollBoxAdj = this.applicationsScrollBox.get_vscroll_bar().get_adjustment();
|
let tree = appsys.get_tree();
|
||||||
let appsScrollBoxAlloc = this.applicationsScrollBox.get_allocation_box();
|
let root = tree.get_root_directory();
|
||||||
let currentScrollValue = appsScrollBoxAdj.get_value();
|
|
||||||
let boxHeight = appsScrollBoxAlloc.y2 - appsScrollBoxAlloc.y1;
|
|
||||||
let buttonAlloc = button.get_allocation_box();
|
|
||||||
let newScrollValue = currentScrollValue;
|
|
||||||
if (currentScrollValue > buttonAlloc.y1 - 10)
|
|
||||||
newScrollValue = buttonAlloc.y1 - 10;
|
|
||||||
if (boxHeight + currentScrollValue < buttonAlloc.y2 + 10)
|
|
||||||
newScrollValue = buttonAlloc.y2 - boxHeight + 10;
|
|
||||||
if (newScrollValue !== currentScrollValue)
|
|
||||||
appsScrollBoxAdj.set_value(newScrollValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollToCatButton(button) {
|
|
||||||
let catsScrollBoxAdj = this.categoriesScrollBox.get_vscroll_bar().get_adjustment();
|
|
||||||
let catsScrollBoxAlloc = this.categoriesScrollBox.get_allocation_box();
|
|
||||||
let currentScrollValue = catsScrollBoxAdj.get_value();
|
|
||||||
let boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1;
|
|
||||||
let buttonAlloc = button.get_allocation_box();
|
|
||||||
let newScrollValue = currentScrollValue;
|
|
||||||
if (currentScrollValue > buttonAlloc.y1 - 10)
|
|
||||||
newScrollValue = buttonAlloc.y1 - 10;
|
|
||||||
if (boxHeight + currentScrollValue < buttonAlloc.y2 + 10)
|
|
||||||
newScrollValue = buttonAlloc.y2 - boxHeight + 10;
|
|
||||||
if (newScrollValue !== currentScrollValue)
|
|
||||||
catsScrollBoxAdj.set_value(newScrollValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
_createLayout() {
|
|
||||||
let section = new PopupMenu.PopupMenuSection();
|
|
||||||
this.menu.addMenuItem(section);
|
|
||||||
this.mainBox = new St.BoxLayout({vertical: false});
|
|
||||||
this.leftBox = new St.BoxLayout({vertical: true});
|
|
||||||
this.applicationsScrollBox = new St.ScrollView({
|
|
||||||
style_class: 'apps-menu vfade',
|
|
||||||
x_expand: true,
|
|
||||||
});
|
|
||||||
this.applicationsScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
||||||
let vscroll = this.applicationsScrollBox.get_vscroll_bar();
|
|
||||||
vscroll.connect('scroll-start', () => {
|
|
||||||
this.menu.passEvents = true;
|
|
||||||
});
|
|
||||||
vscroll.connect('scroll-stop', () => {
|
|
||||||
this.menu.passEvents = false;
|
|
||||||
});
|
|
||||||
this.categoriesScrollBox = new St.ScrollView({
|
|
||||||
style_class: 'vfade',
|
|
||||||
});
|
|
||||||
this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
||||||
vscroll = this.categoriesScrollBox.get_vscroll_bar();
|
|
||||||
vscroll.connect('scroll-start', () => (this.menu.passEvents = true));
|
|
||||||
vscroll.connect('scroll-stop', () => (this.menu.passEvents = false));
|
|
||||||
this.leftBox.add_child(this.categoriesScrollBox);
|
|
||||||
|
|
||||||
this.applicationsBox = new St.BoxLayout({vertical: true});
|
|
||||||
this.applicationsScrollBox.add_actor(this.applicationsBox);
|
|
||||||
this.categoriesBox = new St.BoxLayout({vertical: true});
|
|
||||||
this.categoriesScrollBox.add_actor(this.categoriesBox);
|
|
||||||
|
|
||||||
this.mainBox.add(this.leftBox);
|
|
||||||
this.mainBox.add_child(this._createVertSeparator());
|
|
||||||
this.mainBox.add_child(this.applicationsScrollBox);
|
|
||||||
section.actor.add_actor(this.mainBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
_display() {
|
|
||||||
this._applicationsButtons.clear();
|
|
||||||
this.mainBox.style = 'width: 35em;';
|
|
||||||
this.mainBox.hide();
|
|
||||||
|
|
||||||
// Load categories
|
|
||||||
this.applicationsByCategory = {};
|
|
||||||
this._tree.load_sync();
|
|
||||||
let root = this._tree.get_root_directory();
|
|
||||||
let categoryMenuItem = new CategoryMenuItem(this, null);
|
|
||||||
this.categoriesBox.add_actor(categoryMenuItem);
|
|
||||||
let iter = root.iter();
|
let iter = root.iter();
|
||||||
let nextType;
|
let nextType;
|
||||||
while ((nextType = iter.next()) !== GMenu.TreeItemType.INVALID) {
|
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
|
||||||
if (nextType !== GMenu.TreeItemType.DIRECTORY)
|
if (nextType == GMenu.TreeItemType.DIRECTORY) {
|
||||||
continue;
|
let dir = iter.get_directory();
|
||||||
|
let item = new PopupMenu.PopupSubMenuMenuItem(dir.get_name());
|
||||||
let dir = iter.get_directory();
|
this._loadCategory(dir, item.menu);
|
||||||
if (dir.get_is_nodisplay())
|
this.menu.addMenuItem(item);
|
||||||
continue;
|
|
||||||
|
|
||||||
let categoryId = dir.get_menu_id();
|
|
||||||
this.applicationsByCategory[categoryId] = [];
|
|
||||||
this._loadCategory(categoryId, dir);
|
|
||||||
if (this.applicationsByCategory[categoryId].length > 0) {
|
|
||||||
categoryMenuItem = new CategoryMenuItem(this, dir);
|
|
||||||
this.categoriesBox.add_actor(categoryMenuItem);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load applications
|
|
||||||
this._displayButtons(this._listApplications(null));
|
|
||||||
|
|
||||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
|
||||||
let scaleFactor = themeContext.scale_factor;
|
|
||||||
let categoriesHeight = this.categoriesBox.height / scaleFactor;
|
|
||||||
let height = Math.round(categoriesHeight) + MENU_HEIGHT_OFFSET;
|
|
||||||
this.mainBox.style += `height: ${height}px`;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
selectCategory(dir) {
|
|
||||||
this.applicationsBox.get_children().forEach(c => {
|
|
||||||
if (c._delegate instanceof PopupMenu.PopupSeparatorMenuItem)
|
|
||||||
c._delegate.destroy();
|
|
||||||
else
|
|
||||||
this.applicationsBox.remove_actor(c);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dir)
|
|
||||||
this._displayButtons(this._listApplications(dir.get_menu_id()));
|
|
||||||
else
|
|
||||||
this._displayButtons(this._listApplications(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
_displayButtons(apps) {
|
|
||||||
for (let i = 0; i < apps.length; i++) {
|
|
||||||
let app = apps[i];
|
|
||||||
let item;
|
|
||||||
if (app instanceof Shell.App)
|
|
||||||
item = this._applicationsButtons.get(app);
|
|
||||||
else
|
|
||||||
item = new PopupMenu.PopupSeparatorMenuItem();
|
|
||||||
if (!item) {
|
|
||||||
item = new ApplicationMenuItem(this, app);
|
|
||||||
item.setDragEnabled(this._desktopTarget.hasDesktop);
|
|
||||||
this._applicationsButtons.set(app, item);
|
|
||||||
}
|
|
||||||
if (!item.get_parent())
|
|
||||||
this.applicationsBox.add_actor(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_listApplications(categoryMenuId) {
|
|
||||||
let applist;
|
|
||||||
|
|
||||||
if (categoryMenuId) {
|
|
||||||
applist = this.applicationsByCategory[categoryMenuId];
|
|
||||||
} else {
|
|
||||||
applist = global.settings.get_strv('favorite-apps')
|
|
||||||
.map(id => appSys.lookup_app(id))
|
|
||||||
.filter(app => app);
|
|
||||||
}
|
|
||||||
|
|
||||||
return applist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let appsMenuButton;
|
let appsMenuButton;
|
||||||
|
|
||||||
/** */
|
|
||||||
function enable() {
|
function enable() {
|
||||||
appsMenuButton = new ApplicationsButton();
|
appsMenuButton = new ApplicationsButton();
|
||||||
let index = Main.sessionMode.panel.left.indexOf('activities') + 1;
|
Main.panel._leftBox.insert_actor(appsMenuButton.actor, 1);
|
||||||
Main.panel.addToStatusArea('apps-menu', appsMenuButton, index, 'left');
|
Main.panel._leftBox.child_set(appsMenuButton.actor, { y_fill : true } );
|
||||||
|
Main.panel._menus.addMenu(appsMenuButton.menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
function disable() {
|
function disable() {
|
||||||
Main.panel.menuManager.removeMenu(appsMenuButton.menu);
|
|
||||||
appsMenuButton.destroy();
|
appsMenuButton.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
function init() {
|
function init() {
|
||||||
ExtensionUtils.initTranslations();
|
/* do nothing */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
extension_data += configure_file(
|
|
||||||
input: metadata_name + '.in',
|
|
||||||
output: metadata_name,
|
|
||||||
configuration: metadata_conf
|
|
||||||
)
|
|
||||||
extension_data += files('stylesheet.css')
|
|
||||||
extension_schemas += files(metadata_conf.get('gschemaname') + '.gschema.xml')
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extension-id": "@extension_id@",
|
|
||||||
"uuid": "@uuid@",
|
"uuid": "@uuid@",
|
||||||
"settings-schema": "@gschemaname@",
|
|
||||||
"gettext-domain": "@gettext_domain@",
|
|
||||||
"name": "Applications Menu",
|
"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's GitLab instance instead.",
|
"description": "Add a gnome 2.x style menu for applications",
|
||||||
"original-authors": [ "e2002@bk.ru", "debarshir@gnome.org" ],
|
"shell-version": [ "@shell_current@", "3.2" ],
|
||||||
"shell-version": [ "@shell_current@" ],
|
|
||||||
"url": "@url@"
|
"url": "@url@"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<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>["<Alt>F1"]</default>
|
|
||||||
<summary>Keybinding to open the applications menu</summary>
|
|
||||||
<description>
|
|
||||||
Keybinding to open the applications menu.
|
|
||||||
</description>
|
|
||||||
</key>
|
|
||||||
</schema>
|
|
||||||
</schemalist>
|
|
||||||
@@ -1,7 +1 @@
|
|||||||
.apps-menu:ltr {
|
/* none used*/
|
||||||
padding-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.apps-menu:rtl {
|
|
||||||
padding-left: 3px;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
EXTENSION_ID = auto-move-windows
|
||||||
|
|
||||||
|
include ../../extension.mk
|
||||||
|
|
||||||
|
gschemas_in = $(gschemabase).auto-move-windows.gschema.xml.in
|
||||||
|
|
||||||
|
@INTLTOOL_XML_NOMERGE_RULE@
|
||||||
|
|
||||||
|
gsettings_SCHEMAS = $(gschemas_in:.xml.in=.xml)
|
||||||
|
|
||||||
|
@GSETTINGS_RULES@
|
||||||
|
|
||||||
|
CLEANFILES += $(gschemas_in:.xml.in=.valid) $(gsettings_SCHEMAS)
|
||||||
|
EXTRA_DIST += $(gschemas_in)
|
||||||
@@ -1,151 +1,162 @@
|
|||||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
||||||
// Start apps on custom workspaces
|
// Start apps on custom workspaces
|
||||||
/* exported init enable disable */
|
|
||||||
|
|
||||||
const {Shell} = imports.gi;
|
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 ExtensionUtils = imports.misc.extensionUtils;
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
|
||||||
class WindowMover {
|
const SETTINGS_SCHEMA = 'org.gnome.shell.extensions.auto-move-windows';
|
||||||
constructor() {
|
const SETTINGS_KEY = 'application-list';
|
||||||
this._settings = ExtensionUtils.getSettings();
|
|
||||||
this._appSystem = Shell.AppSystem.get_default();
|
|
||||||
this._appConfigs = new Map();
|
|
||||||
this._appData = new Map();
|
|
||||||
|
|
||||||
this._appsChangedId =
|
function WindowMover() {
|
||||||
this._appSystem.connect('installed-changed',
|
this._init();
|
||||||
this._updateAppData.bind(this));
|
}
|
||||||
|
|
||||||
this._settings.connect('changed', this._updateAppConfigs.bind(this));
|
WindowMover.prototype = {
|
||||||
this._updateAppConfigs();
|
_init: function() {
|
||||||
}
|
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
|
||||||
|
this._windowTracker = Shell.WindowTracker.get_default();
|
||||||
|
|
||||||
_updateAppConfigs() {
|
let display = global.screen.get_display();
|
||||||
this._appConfigs.clear();
|
// Connect after so the handler from ShellWindowTracker has already run
|
||||||
|
this._windowCreatedId = display.connect_after('window-created', Lang.bind(this, this._findAndMove));
|
||||||
|
},
|
||||||
|
|
||||||
this._settings.get_strv('application-list').forEach(v => {
|
destroy: function() {
|
||||||
let [appId, num] = v.split(':');
|
if (this._windowCreatedId) {
|
||||||
this._appConfigs.set(appId, parseInt(num) - 1);
|
global.screen.get_display().disconnect(this._windowCreatedId);
|
||||||
});
|
this._windowCreatedId = 0;
|
||||||
|
|
||||||
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) {
|
_ensureAtLeastWorkspaces: function(num, window) {
|
||||||
this._settings.run_dispose();
|
for (let j = global.screen.n_workspaces; j <= num; j++) {
|
||||||
this._settings = null;
|
window.change_workspace_by_index(j-1, false, global.get_current_time());
|
||||||
|
global.screen.append_new_workspace(false, 0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
this._appConfigs.clear();
|
_findAndMove: function(display, window, noRecurse) {
|
||||||
this._updateAppData();
|
if (!this._windowTracker.is_window_interesting(window))
|
||||||
}
|
|
||||||
|
|
||||||
_moveWindow(window, workspaceNum) {
|
|
||||||
if (window.skip_taskbar || window.is_on_all_workspaces())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// ensure we have the required number of workspaces
|
let spaces = this._settings.get_strv(SETTINGS_KEY);
|
||||||
let workspaceManager = global.workspace_manager;
|
|
||||||
for (let i = workspaceManager.n_workspaces; i <= workspaceNum; i++) {
|
let app = this._windowTracker.get_window_app(window);
|
||||||
window.change_workspace_by_index(i - 1, false);
|
if (!app) {
|
||||||
workspaceManager.append_new_workspace(false, 0);
|
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;
|
||||||
|
|
||||||
window.change_workspace_by_index(workspaceNum, false);
|
if (workspace_num >= global.screen.n_workspaces)
|
||||||
}
|
this._ensureAtLeastWorkspaces(workspace_num, window);
|
||||||
|
|
||||||
_appWindowsChanged(app) {
|
window.change_workspace_by_index(workspace_num, false, global.get_current_time());
|
||||||
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 prevCheckWorkspaces;
|
||||||
let winMover;
|
let winMover;
|
||||||
|
|
||||||
/** */
|
function init(extensionMeta) {
|
||||||
function init() {
|
// do nothing here
|
||||||
ExtensionUtils.initTranslations();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {bool} - false (used as MetaLater handler)
|
|
||||||
*/
|
|
||||||
function myCheckWorkspaces() {
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** */
|
|
||||||
function enable() {
|
function enable() {
|
||||||
prevCheckWorkspaces = Main.wm._workspaceTracker._checkWorkspaces;
|
prevCheckWorkspaces = Main._checkWorkspaces;
|
||||||
Main.wm._workspaceTracker._checkWorkspaces = myCheckWorkspaces;
|
Main._checkWorkspaces = function() {
|
||||||
|
let i;
|
||||||
|
let emptyWorkspaces = new Array(Main._workspaces.length);
|
||||||
|
|
||||||
|
for (i = 0; i < Main._workspaces.length; i++) {
|
||||||
|
let lastRemoved = Main._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))
|
||||||
|
emptyWorkspaces[i] = false;
|
||||||
|
else
|
||||||
|
emptyWorkspaces[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let windows = global.get_window_actors();
|
||||||
|
for (i = 0; i < windows.length; i++) {
|
||||||
|
let win = windows[i];
|
||||||
|
|
||||||
|
if (win.get_meta_window().is_on_all_workspaces())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let workspaceIndex = win.get_workspace();
|
||||||
|
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();
|
||||||
|
let activeIsLast = activeWorkspaceIndex == global.screen.n_workspaces - 2;
|
||||||
|
let removingTrailWorkspaces = (emptyWorkspaces[activeWorkspaceIndex] &&
|
||||||
|
activeIsLast);
|
||||||
|
// Don't enter the overview when removing multiple empty workspaces at startup
|
||||||
|
let showOverview = (removingTrailWorkspaces &&
|
||||||
|
!emptyWorkspaces.every(function(x) { return x; }));
|
||||||
|
|
||||||
|
if (removingTrailWorkspaces) {
|
||||||
|
// "Merge" the empty workspace we are removing with the one at the end
|
||||||
|
Main.wm.blockAnimations();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(Main._workspaces[i], global.get_current_time());
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removingTrailWorkspaces) {
|
||||||
|
global.screen.get_workspace_by_index(global.screen.n_workspaces - 1).activate(global.get_current_time());
|
||||||
|
|
||||||
|
Main.wm.unblockAnimations();
|
||||||
|
|
||||||
|
if (!Main.overview.visible && showOverview)
|
||||||
|
Main.overview.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
Main._checkWorkspacesId = 0;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
winMover = new WindowMover();
|
winMover = new WindowMover();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
function disable() {
|
function disable() {
|
||||||
Main.wm._workspaceTracker._checkWorkspaces = prevCheckWorkspaces;
|
Main._checkWorkspaces = prevCheckWorkspaces;
|
||||||
winMover.destroy();
|
winMover.destroy();
|
||||||
}
|
}
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
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')
|
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
{
|
{
|
||||||
"extension-id": "@extension_id@",
|
|
||||||
"uuid": "@uuid@",
|
"uuid": "@uuid@",
|
||||||
"settings-schema": "@gschemaname@",
|
|
||||||
"gettext-domain": "@gettext_domain@",
|
|
||||||
"name": "Auto Move Windows",
|
"name": "Auto Move Windows",
|
||||||
"description": "Move applications to specific workspaces when they create windows.",
|
"description": "Move applications to specific workspaces when they create windows",
|
||||||
"shell-version": [ "@shell_current@" ],
|
"shell-version": [ "@shell_current@", "3.2" ],
|
||||||
"original-authors": [ "alessandro.crismani@gmail.com", "thomas.bouffon@gmail.com" ],
|
"original-authors": [ "alessandro.crismani@gmail.com", "thomas.bouffon@gmail.com" ],
|
||||||
"url": "@url@"
|
"url": "@url@"
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -3,8 +3,8 @@
|
|||||||
<key name="application-list" type="as">
|
<key name="application-list" type="as">
|
||||||
<!-- FIXME: should be a(su), when JS supports more of GVariant -->
|
<!-- FIXME: should be a(su), when JS supports more of GVariant -->
|
||||||
<default>[ ]</default>
|
<default>[ ]</default>
|
||||||
<summary>Application and workspace list</summary>
|
<_summary>Application and workspace list</_summary>
|
||||||
<description>A list of strings, each containing an application id (desktop file name), followed by a colon and the workspace number</description>
|
<_description>A list of strings, each containing an application id (desktop file name), followed by a colon and the workspace number</_description>
|
||||||
</key>
|
</key>
|
||||||
</schema>
|
</schema>
|
||||||
</schemalist>
|
</schemalist>
|
||||||
@@ -1,351 +0,0 @@
|
|||||||
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
|
|
||||||
// Start apps on custom workspaces
|
|
||||||
/* exported init buildPrefsWidget */
|
|
||||||
|
|
||||||
const {Adw, Gio, GLib, GObject, Gtk} = imports.gi;
|
|
||||||
|
|
||||||
const ExtensionUtils = imports.misc.extensionUtils;
|
|
||||||
|
|
||||||
const _ = ExtensionUtils.gettext;
|
|
||||||
|
|
||||||
const SETTINGS_KEY = 'application-list';
|
|
||||||
|
|
||||||
const WORKSPACE_MAX = 36; // compiled in limit of mutter
|
|
||||||
|
|
||||||
class NewItem extends GObject.Object {}
|
|
||||||
GObject.registerClass(NewItem);
|
|
||||||
|
|
||||||
class NewItemModel extends GObject.Object {
|
|
||||||
static [GObject.interfaces] = [Gio.ListModel];
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
#item = new NewItem();
|
|
||||||
|
|
||||||
vfunc_get_item_type() {
|
|
||||||
return NewItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_get_n_items() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_get_item(_pos) {
|
|
||||||
return this.#item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Rule extends GObject.Object {
|
|
||||||
static [GObject.properties] = {
|
|
||||||
'app-info': GObject.ParamSpec.object(
|
|
||||||
'app-info', 'app-info', 'app-info',
|
|
||||||
GObject.ParamFlags.READWRITE,
|
|
||||||
Gio.DesktopAppInfo),
|
|
||||||
'workspace': GObject.ParamSpec.uint(
|
|
||||||
'workspace', 'workspace', 'workspace',
|
|
||||||
GObject.ParamFlags.READWRITE,
|
|
||||||
1, WORKSPACE_MAX, 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RulesList extends GObject.Object {
|
|
||||||
static [GObject.interfaces] = [Gio.ListModel];
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
#settings = ExtensionUtils.getSettings();
|
|
||||||
#rules = [];
|
|
||||||
#changedId;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.#changedId =
|
|
||||||
this.#settings.connect(`changed::${SETTINGS_KEY}`,
|
|
||||||
() => this.#sync());
|
|
||||||
this.#sync();
|
|
||||||
}
|
|
||||||
|
|
||||||
append(appInfo) {
|
|
||||||
const pos = this.#rules.length;
|
|
||||||
|
|
||||||
this.#rules.push(new Rule({appInfo}));
|
|
||||||
this.#saveRules();
|
|
||||||
|
|
||||||
this.items_changed(pos, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(id) {
|
|
||||||
const pos = this.#rules.findIndex(r => r.appInfo.get_id() === id);
|
|
||||||
if (pos < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.#rules.splice(pos, 1);
|
|
||||||
this.#saveRules();
|
|
||||||
|
|
||||||
this.items_changed(pos, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
changeWorkspace(id, workspace) {
|
|
||||||
const pos = this.#rules.findIndex(r => r.appInfo.get_id() === id);
|
|
||||||
if (pos < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.#rules[pos].set({workspace});
|
|
||||||
this.#saveRules();
|
|
||||||
}
|
|
||||||
|
|
||||||
#saveRules() {
|
|
||||||
this.#settings.block_signal_handler(this.#changedId);
|
|
||||||
this.#settings.set_strv(SETTINGS_KEY,
|
|
||||||
this.#rules.map(r => `${r.app_info.get_id()}:${r.workspace}`));
|
|
||||||
this.#settings.unblock_signal_handler(this.#changedId);
|
|
||||||
}
|
|
||||||
|
|
||||||
#sync() {
|
|
||||||
const removed = this.#rules.length;
|
|
||||||
|
|
||||||
this.#rules = [];
|
|
||||||
for (const stringRule of this.#settings.get_strv(SETTINGS_KEY)) {
|
|
||||||
const [id, workspace] = stringRule.split(':');
|
|
||||||
const appInfo = Gio.DesktopAppInfo.new(id);
|
|
||||||
if (appInfo)
|
|
||||||
this.#rules.push(new Rule({appInfo, workspace}));
|
|
||||||
else
|
|
||||||
log(`Invalid ID ${id}`);
|
|
||||||
}
|
|
||||||
this.items_changed(0, removed, this.#rules.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_get_item_type() {
|
|
||||||
return Rule;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_get_n_items() {
|
|
||||||
return this.#rules.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
vfunc_get_item(pos) {
|
|
||||||
return this.#rules[pos] ?? null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AutoMoveSettingsWidget extends Adw.PreferencesGroup {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
|
|
||||||
this.install_action('rules.add', null, self => self._addNewRule());
|
|
||||||
this.install_action('rules.remove', 's',
|
|
||||||
(self, name, param) => self._rules.remove(param.unpack()));
|
|
||||||
this.install_action('rules.change-workspace', '(si)',
|
|
||||||
(self, name, param) => self._rules.changeWorkspace(...param.deepUnpack()));
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
title: _('Workspace Rules'),
|
|
||||||
});
|
|
||||||
|
|
||||||
this._rules = new RulesList();
|
|
||||||
|
|
||||||
const store = new Gio.ListStore({item_type: Gio.ListModel});
|
|
||||||
const listModel = new Gtk.FlattenListModel({model: store});
|
|
||||||
store.append(this._rules);
|
|
||||||
store.append(new NewItemModel());
|
|
||||||
|
|
||||||
this._list = new Gtk.ListBox({
|
|
||||||
selection_mode: Gtk.SelectionMode.NONE,
|
|
||||||
css_classes: ['boxed-list'],
|
|
||||||
});
|
|
||||||
this.add(this._list);
|
|
||||||
|
|
||||||
this._list.bind_model(listModel, item => {
|
|
||||||
return item instanceof NewItem
|
|
||||||
? new NewRuleRow()
|
|
||||||
: new RuleRow(item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_addNewRule() {
|
|
||||||
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._rules.append(appInfo);
|
|
||||||
dialog.destroy();
|
|
||||||
});
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WorkspaceSelector extends Gtk.Widget {
|
|
||||||
static [GObject.properties] = {
|
|
||||||
'number': GObject.ParamSpec.uint(
|
|
||||||
'number', 'number', 'number',
|
|
||||||
GObject.ParamFlags.READWRITE,
|
|
||||||
1, WORKSPACE_MAX, 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
|
|
||||||
this.set_layout_manager_type(Gtk.BoxLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.layout_manager.spacing = 6;
|
|
||||||
|
|
||||||
const label = new Gtk.Label({
|
|
||||||
xalign: 1,
|
|
||||||
margin_end: 6,
|
|
||||||
});
|
|
||||||
this.bind_property('number',
|
|
||||||
label, 'label',
|
|
||||||
GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
label.set_parent(this);
|
|
||||||
|
|
||||||
const buttonProps = {
|
|
||||||
css_classes: ['circular'],
|
|
||||||
valign: Gtk.Align.CENTER,
|
|
||||||
};
|
|
||||||
|
|
||||||
this._decButton = new Gtk.Button({
|
|
||||||
icon_name: 'list-remove-symbolic',
|
|
||||||
...buttonProps,
|
|
||||||
});
|
|
||||||
this._decButton.set_parent(this);
|
|
||||||
this._decButton.connect('clicked', () => this.number--);
|
|
||||||
|
|
||||||
this._incButton = new Gtk.Button({
|
|
||||||
icon_name: 'list-add-symbolic',
|
|
||||||
...buttonProps,
|
|
||||||
});
|
|
||||||
this._incButton.set_parent(this);
|
|
||||||
this._incButton.connect('clicked', () => this.number++);
|
|
||||||
|
|
||||||
this.connect('notify::number', () => this._syncButtons());
|
|
||||||
this._syncButtons();
|
|
||||||
}
|
|
||||||
|
|
||||||
_syncButtons() {
|
|
||||||
this._decButton.sensitive = this.number > 1;
|
|
||||||
this._incButton.sensitive = this.number < WORKSPACE_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class RuleRow extends Adw.ActionRow {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(rule) {
|
|
||||||
const {appInfo} = rule;
|
|
||||||
const id = appInfo.get_id();
|
|
||||||
|
|
||||||
super({
|
|
||||||
activatable: false,
|
|
||||||
title: rule.appInfo.get_display_name(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const icon = new Gtk.Image({
|
|
||||||
css_classes: ['icon-dropshadow'],
|
|
||||||
gicon: appInfo.get_icon(),
|
|
||||||
pixel_size: 32,
|
|
||||||
});
|
|
||||||
this.add_prefix(icon);
|
|
||||||
|
|
||||||
const wsButton = new WorkspaceSelector();
|
|
||||||
rule.bind_property('workspace',
|
|
||||||
wsButton, 'number',
|
|
||||||
GObject.BindingFlags.SYNC_CREATE);
|
|
||||||
this.add_suffix(wsButton);
|
|
||||||
|
|
||||||
wsButton.connect('notify::number', () => {
|
|
||||||
this.activate_action('rules.change-workspace',
|
|
||||||
new GLib.Variant('(si)', [id, wsButton.number]));
|
|
||||||
});
|
|
||||||
|
|
||||||
const button = new Gtk.Button({
|
|
||||||
action_name: 'rules.remove',
|
|
||||||
action_target: new GLib.Variant('s', id),
|
|
||||||
icon_name: 'edit-delete-symbolic',
|
|
||||||
has_frame: false,
|
|
||||||
valign: Gtk.Align.CENTER,
|
|
||||||
});
|
|
||||||
this.add_suffix(button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NewRuleRow extends Gtk.ListBoxRow {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
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')]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class NewRuleDialog extends Gtk.AppChooserDialog {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(parent) {
|
|
||||||
super({
|
|
||||||
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() {
|
|
||||||
ExtensionUtils.initTranslations();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {Gtk.Widget} - the prefs widget
|
|
||||||
*/
|
|
||||||
function buildPrefsWidget() {
|
|
||||||
return new AutoMoveSettingsWidget();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/* This extensions requires no special styling */
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
EXTENSION_ID = dock
|
||||||
|
|
||||||
|
include ../../extension.mk
|
||||||
|
|
||||||
|
gschemas_in = $(gschemabase).dock.gschema.xml.in
|
||||||
|
|
||||||
|
@INTLTOOL_XML_NOMERGE_RULE@
|
||||||
|
|
||||||
|
gsettings_SCHEMAS = $(gschemas_in:.xml.in=.xml)
|
||||||
|
|
||||||
|
@GSETTINGS_RULES@
|
||||||
|
|
||||||
|
CLEANFILES += $(gschemas_in:.xml.in=.valid) $(gsettings_SCHEMAS)
|
||||||
|
EXTRA_DIST += $(gschemas_in)
|
||||||
@@ -0,0 +1,950 @@
|
|||||||
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Pango = imports.gi.Pango;
|
||||||
|
const GLib = imports.gi.GLib;
|
||||||
|
const Gio = imports.gi.Gio;
|
||||||
|
const Gtk = imports.gi.Gtk;
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Signals = imports.signals;
|
||||||
|
const St = imports.gi.St;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
|
const AppFavorites = imports.ui.appFavorites;
|
||||||
|
const DND = imports.ui.dnd;
|
||||||
|
const Main = imports.ui.main;
|
||||||
|
const Overview = imports.ui.overview;
|
||||||
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
|
const Search = imports.ui.search;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
const Workspace = imports.ui.workspace;
|
||||||
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
|
const AltTab = imports.ui.altTab;
|
||||||
|
|
||||||
|
const Gettext = imports.gettext.domain('gnome-shell-extensions');
|
||||||
|
const _ = Gettext.gettext;
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
const DOCK_SETTINGS_SCHEMA = 'org.gnome.shell.extensions.dock';
|
||||||
|
const DOCK_POSITION_KEY = 'position';
|
||||||
|
const DOCK_SIZE_KEY = 'size';
|
||||||
|
const DOCK_HIDE_KEY = 'autohide';
|
||||||
|
const DOCK_EFFECTHIDE_KEY = 'hide-effect';
|
||||||
|
const DOCK_AUTOHIDE_ANIMATION_TIME_KEY = 'hide-effect-duration';
|
||||||
|
|
||||||
|
|
||||||
|
//hide
|
||||||
|
//const autohide_animation_time = 0.3;
|
||||||
|
|
||||||
|
// Keep enums in sync with GSettings schemas
|
||||||
|
const PositionMode = {
|
||||||
|
LEFT: 0,
|
||||||
|
RIGHT: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const AutoHideEffect = {
|
||||||
|
RESIZE: 0,
|
||||||
|
RESCALE: 1,
|
||||||
|
MOVE: 2
|
||||||
|
};
|
||||||
|
|
||||||
|
let position = PositionMode.RIGHT;
|
||||||
|
let dockicon_size = 48;
|
||||||
|
let hideable = true;
|
||||||
|
let hideDock = true;
|
||||||
|
let hideEffect = AutoHideEffect.RESIZE;
|
||||||
|
let autohide_animation_time = 0.3;
|
||||||
|
const DND_RAISE_APP_TIMEOUT = 500;
|
||||||
|
|
||||||
|
/*************************************************************************************/
|
||||||
|
/**** start resize's Dock functions *****************/
|
||||||
|
/*************************************************************************************/
|
||||||
|
function hideDock_size () {
|
||||||
|
if (hideable){
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor
|
||||||
|
let position_x = monitor.x;
|
||||||
|
let height = (this._nicons)*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
Tweener.addTween(this,{
|
||||||
|
_item_size: 1,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onUpdate: function () {
|
||||||
|
height = (this._nicons)*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
width = this._item_size + 4*this._spacing;
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
position_x=monitor.x-2*this._spacing;
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
position_x = monitor.x + (monitor.width-1-this._item_size-2*this._spacing);
|
||||||
|
}
|
||||||
|
this.actor.set_position (position_x,monitor.y+(monitor.height-height)/2);
|
||||||
|
this.actor.set_size(width,height);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
hideDock=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDock_size () {
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let height = (this._nicons)*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
let position_x = monitor.x;
|
||||||
|
|
||||||
|
Tweener.addTween(this,{
|
||||||
|
_item_size: dockicon_size,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onUpdate: function () {
|
||||||
|
height = (this._nicons)*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
width = this._item_size + 4*this._spacing;
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
position_x=monitor.x-2*this._spacing;
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
position_x=monitor.x + (monitor.width-this._item_size-2*this._spacing);
|
||||||
|
}
|
||||||
|
this.actor.set_position (position_x, monitor.y+(monitor.height-height)/2);
|
||||||
|
this.actor.set_size(width,height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
hideDock=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initShowDock_size () {
|
||||||
|
this._item_size=1;
|
||||||
|
this._showDock();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEffectAddItem_size () {
|
||||||
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
|
let height = (this._nicons)*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
y: primary.y + (primary.height-height)/2,
|
||||||
|
height: height,
|
||||||
|
width: width,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************/
|
||||||
|
/**** start rescale's Dock functions *****************/
|
||||||
|
/**************************************************************************************/
|
||||||
|
function hideDock_scale () {
|
||||||
|
this._item_size = dockicon_size;
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let cornerX = 0;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
cornerX=monitor.x;
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
cornerX = monitor.x + monitor.width-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hideable) {
|
||||||
|
Tweener.addTween(this.actor,{
|
||||||
|
y: monitor.y + (monitor.height-height)/2,
|
||||||
|
x: cornerX,
|
||||||
|
height:height,
|
||||||
|
width: width,
|
||||||
|
scale_x: 0.025,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
hideDock=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDock_scale () {
|
||||||
|
this._item_size = dockicon_size;
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let position_x = monitor.x;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
position_x=monitor.x-2*this._spacing;
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
position_x=monitor.x + (monitor.width-this._item_size-2*this._spacing);
|
||||||
|
}
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
y: monitor.y + (monitor.height-height)/2,
|
||||||
|
x: monitor.x + position_x,
|
||||||
|
height: height,
|
||||||
|
width: width,
|
||||||
|
scale_x: 1,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
hideDock=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initShowDock_scale () {
|
||||||
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
this.actor.set_scale (0,0);
|
||||||
|
this.actor.set_size (width,height);
|
||||||
|
|
||||||
|
// set the position of the dock
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
this.actor.x = 0;
|
||||||
|
// effect of creation of the dock
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
x: primary.x-2*this._spacing,
|
||||||
|
y: primary.y + (primary.height-height)/2,
|
||||||
|
time: autohide_animation_time * 3,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
this.actor.x = primary.width-1;
|
||||||
|
// effect of creation of the dock
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
x: primary.x + primary.width-this._item_size- 2*this._spacing,
|
||||||
|
y: primary.y + (primary.height-height)/2,
|
||||||
|
time: autohide_animation_time * 3,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Tweener.addTween(this.actor,{
|
||||||
|
scale_x: 1,
|
||||||
|
scale_y: 1,
|
||||||
|
time: autohide_animation_time * 3,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
hideDock=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEffectAddItem_scale () {
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
y: monitor.y + (monitor.height-height)/2,
|
||||||
|
height: height,
|
||||||
|
width: width,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************/
|
||||||
|
/**** start move Dock functions *****************/
|
||||||
|
/**************************************************************************************/
|
||||||
|
function hideDock_move () {
|
||||||
|
this._item_size = dockicon_size;
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let cornerX = 0;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
cornerX= monitor.x - width + this._spacing;
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
cornerX = monitor.x + monitor.width - this._spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hideable) {
|
||||||
|
Tweener.addTween(this.actor,{
|
||||||
|
x: cornerX,
|
||||||
|
y: monitor.y + (monitor.height - height)/2,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
hideDock=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDock_move () {
|
||||||
|
this._item_size = dockicon_size;
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let position_x = monitor.x;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
position_x=monitor.x - 2*this._spacing;
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
position_x=monitor.x + (monitor.width-this._item_size-2*this._spacing);
|
||||||
|
}
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
x: position_x,
|
||||||
|
y: monitor.y + (monitor.height - height)/2,
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
hideDock=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initShowDock_move () {
|
||||||
|
this._showDock();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showEffectAddItem_move () {
|
||||||
|
let monitor = Main.layoutManager.primaryMonitor;
|
||||||
|
let height = this._nicons*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
Tweener.addTween(this.actor, {
|
||||||
|
y: monitor.y + (monitor.height-height)/2,
|
||||||
|
height: height,
|
||||||
|
width: width,
|
||||||
|
time: autohide_animation_time,
|
||||||
|
transition: 'easeOutQuad'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function Dock() {
|
||||||
|
this._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
Dock.prototype = {
|
||||||
|
_init : function() {
|
||||||
|
this._placeholderText = null;
|
||||||
|
this._menus = [];
|
||||||
|
this._menuDisplays = [];
|
||||||
|
|
||||||
|
this._favorites = [];
|
||||||
|
|
||||||
|
// Load Settings
|
||||||
|
this._settings = new Gio.Settings({ schema: DOCK_SETTINGS_SCHEMA });
|
||||||
|
position = this._settings.get_enum(DOCK_POSITION_KEY);
|
||||||
|
dockicon_size = this._settings.get_int(DOCK_SIZE_KEY);
|
||||||
|
hideDock = hideable = this._settings.get_boolean(DOCK_HIDE_KEY);
|
||||||
|
hideEffect = this._settings.get_enum(DOCK_EFFECTHIDE_KEY);
|
||||||
|
autohide_animation_time = this._settings.get_double(DOCK_AUTOHIDE_ANIMATION_TIME_KEY);
|
||||||
|
//global.log("POSITION: " + position);
|
||||||
|
//global.log("dockicon_size: " + dockicon_size);
|
||||||
|
|
||||||
|
|
||||||
|
this._spacing = 4;
|
||||||
|
this._item_size = dockicon_size;
|
||||||
|
this._nicons = 0;
|
||||||
|
this._selectFunctionsHide ();
|
||||||
|
|
||||||
|
this.actor = new St.BoxLayout({ name: 'dock', vertical: true, reactive: true });
|
||||||
|
|
||||||
|
this._grid = new Shell.GenericContainer();
|
||||||
|
this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
|
||||||
|
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
|
||||||
|
|
||||||
|
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||||
|
this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||||
|
this._grid.connect('allocate', Lang.bind(this, this._allocate));
|
||||||
|
|
||||||
|
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
|
||||||
|
|
||||||
|
this._tracker = Shell.WindowTracker.get_default();
|
||||||
|
this._appSystem = Shell.AppSystem.get_default();
|
||||||
|
|
||||||
|
this._installedChangedId = this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
|
||||||
|
this._appFavoritesChangedId = AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
|
||||||
|
this._appStateChangedId = this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
|
||||||
|
|
||||||
|
this._overviewShowingId = Main.overview.connect('showing', Lang.bind(this, function() {
|
||||||
|
this.actor.hide();
|
||||||
|
}));
|
||||||
|
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this, function() {
|
||||||
|
this.actor.show();
|
||||||
|
}));
|
||||||
|
Main.layoutManager.addChrome(this.actor);
|
||||||
|
|
||||||
|
//hidden
|
||||||
|
this._settings.connect('changed::'+DOCK_POSITION_KEY, Lang.bind(this, function (){
|
||||||
|
if (!this._settings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
|
position = this._settings.get_enum(DOCK_POSITION_KEY);
|
||||||
|
this.actor.y=primary.y;
|
||||||
|
this._redisplay();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._settings.connect('changed::'+DOCK_SIZE_KEY, Lang.bind(this, function (){
|
||||||
|
if (!this._settings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dockicon_size = this._settings.get_int(DOCK_SIZE_KEY);
|
||||||
|
this._redisplay();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._settings.connect('changed::'+DOCK_HIDE_KEY, Lang.bind(this, function (){
|
||||||
|
if (!this._settings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hideable = this._settings.get_boolean(DOCK_HIDE_KEY);
|
||||||
|
if (hideable){
|
||||||
|
hideDock=false;
|
||||||
|
this._hideDock();
|
||||||
|
} else {
|
||||||
|
hideDock=true;
|
||||||
|
this._showDock();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._settings.connect('changed::'+DOCK_EFFECTHIDE_KEY, Lang.bind(this, function () {
|
||||||
|
if (!this._settings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hideEffect = this._settings.get_enum(DOCK_EFFECTHIDE_KEY);
|
||||||
|
|
||||||
|
switch (hideEffect) {
|
||||||
|
case AutoHideEffect.RESCALE:
|
||||||
|
this._item_size=dockicon_size;
|
||||||
|
break;
|
||||||
|
case AutoHideEffect.RESIZE:
|
||||||
|
this.actor.set_scale (1,1);
|
||||||
|
break;
|
||||||
|
case AutoHideEffect.MOVE:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
this.actor.disconnect(this._leave_event);
|
||||||
|
this.actor.disconnect(this._enter_event);
|
||||||
|
|
||||||
|
this._selectFunctionsHide ();
|
||||||
|
|
||||||
|
this._leave_event = this.actor.connect('leave-event', Lang.bind(this, this._hideDock));
|
||||||
|
this._enter_event = this.actor.connect('enter-event', Lang.bind(this, this._showDock));
|
||||||
|
this._redisplay();
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._settings.connect('changed::'+DOCK_AUTOHIDE_ANIMATION_TIME_KEY, Lang.bind(this,function (){
|
||||||
|
if (!this._settings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
autohide_animation_time = this._settings.get_double(DOCK_AUTOHIDE_ANIMATION_TIME_KEY);
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._leave_event = this.actor.connect('leave-event', Lang.bind(this, this._hideDock));
|
||||||
|
this._enter_event = this.actor.connect('enter-event', Lang.bind(this, this._showDock));
|
||||||
|
|
||||||
|
this._hideDock();
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function() {
|
||||||
|
if (this._installedChangedId) {
|
||||||
|
this._appSystem.disconnect(this._installedChangedId);
|
||||||
|
this._installedChangedId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._appFavoritesChangedId) {
|
||||||
|
AppFavorites.getAppFavorites().disconnect(this._appFavoritesChangedId);
|
||||||
|
this._appFavoritesChangedId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._appStateChangedId) {
|
||||||
|
this._appSystem.disconnect(this._appStateChangedId);
|
||||||
|
this._appStateChangedId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._overviewShowingId) {
|
||||||
|
Main.overview.disconnect(this._overviewShowingId);
|
||||||
|
this._overviewShowingId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._overviewHiddenId) {
|
||||||
|
Main.overview.disconnect(this._overviewHiddenId);
|
||||||
|
this._overviewHiddenId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.destroy();
|
||||||
|
|
||||||
|
// Break reference cycles
|
||||||
|
this._settings = null;
|
||||||
|
this._appSystem = null;
|
||||||
|
this._tracker = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// fuctions hide
|
||||||
|
_restoreHideDock: function(){
|
||||||
|
hideable = this._settings.get_boolean(DOCK_HIDE_KEY);
|
||||||
|
},
|
||||||
|
|
||||||
|
_disableHideDock: function (){
|
||||||
|
hideable = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_selectFunctionsHide: function () {
|
||||||
|
switch (hideEffect) {
|
||||||
|
case AutoHideEffect.RESCALE:
|
||||||
|
this._hideDock = hideDock_scale;
|
||||||
|
this._showDock = showDock_scale;
|
||||||
|
this._initShowDock = initShowDock_scale;
|
||||||
|
this._showEffectAddItem = showEffectAddItem_scale;
|
||||||
|
break;
|
||||||
|
case AutoHideEffect.MOVE:
|
||||||
|
this._hideDock = hideDock_move;
|
||||||
|
this._showDock = showDock_move;
|
||||||
|
this._initShowDock = initShowDock_move;
|
||||||
|
this._showEffectAddItem = showEffectAddItem_move;
|
||||||
|
break;
|
||||||
|
case AutoHideEffect.RESIZE:
|
||||||
|
default:
|
||||||
|
this._hideDock = hideDock_size;
|
||||||
|
this._showDock = showDock_size;
|
||||||
|
this._initShowDock = initShowDock_size;
|
||||||
|
this._showEffectAddItem = showEffectAddItem_size;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_appIdListToHash: function(apps) {
|
||||||
|
let ids = {};
|
||||||
|
for (let i = 0; i < apps.length; i++)
|
||||||
|
ids[apps[i].get_id()] = apps[i];
|
||||||
|
return ids;
|
||||||
|
},
|
||||||
|
|
||||||
|
_queueRedisplay: function () {
|
||||||
|
Main.queueDeferredWork(this._workId);
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplay: function () {
|
||||||
|
this.removeAll();
|
||||||
|
|
||||||
|
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
||||||
|
|
||||||
|
let running = this._appSystem.get_running();
|
||||||
|
let runningIds = this._appIdListToHash(running);
|
||||||
|
|
||||||
|
let icons = 0;
|
||||||
|
|
||||||
|
let nFavorites = 0;
|
||||||
|
for (let id in favorites) {
|
||||||
|
let app = favorites[id];
|
||||||
|
let display = new DockIcon(app,this);
|
||||||
|
this.addItem(display.actor);
|
||||||
|
nFavorites++;
|
||||||
|
icons++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < running.length; i++) {
|
||||||
|
let app = running[i];
|
||||||
|
if (app.get_id() in favorites)
|
||||||
|
continue;
|
||||||
|
let display = new DockIcon(app,this);
|
||||||
|
icons++;
|
||||||
|
this.addItem(display.actor);
|
||||||
|
}
|
||||||
|
this._nicons=icons;
|
||||||
|
|
||||||
|
if (this._placeholderText) {
|
||||||
|
this._placeholderText.destroy();
|
||||||
|
this._placeholderText = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (running.length == 0 && nFavorites == 0) {
|
||||||
|
this._placeholderText = new St.Label({ text: _("Drag here to add favorites") });
|
||||||
|
this.actor.add_actor(this._placeholderText);
|
||||||
|
}
|
||||||
|
|
||||||
|
let primary = Main.layoutManager.primaryMonitor;
|
||||||
|
let height = (icons)*(this._item_size + this._spacing) + 2*this._spacing;
|
||||||
|
let width = this._item_size + 4*this._spacing;
|
||||||
|
|
||||||
|
if (this.actor.y != primary.y) {
|
||||||
|
if (hideable && hideDock) {
|
||||||
|
this._hideDock();
|
||||||
|
} else {
|
||||||
|
if (dockicon_size == this._item_size) {
|
||||||
|
// only add/delete icon
|
||||||
|
this._showEffectAddItem ();
|
||||||
|
} else {
|
||||||
|
// change size icon
|
||||||
|
this._showDock ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// effect of creation
|
||||||
|
this._initShowDock ();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredWidth: function (grid, forHeight, alloc) {
|
||||||
|
alloc.min_size = this._item_size;
|
||||||
|
alloc.natural_size = this._item_size + this._spacing;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getPreferredHeight: function (grid, forWidth, alloc) {
|
||||||
|
let children = this._grid.get_children();
|
||||||
|
let nRows = children.length;
|
||||||
|
let totalSpacing = Math.max(0, nRows - 1) * this._spacing;
|
||||||
|
let height = nRows * this._item_size + totalSpacing;
|
||||||
|
alloc.min_size = height;
|
||||||
|
alloc.natural_size = height;
|
||||||
|
},
|
||||||
|
|
||||||
|
_allocate: function (grid, box, flags) {
|
||||||
|
let children = this._grid.get_children();
|
||||||
|
|
||||||
|
let x = box.x1 + this._spacing;
|
||||||
|
if (position == PositionMode.LEFT)
|
||||||
|
x = box.x1 + 2*this._spacing;
|
||||||
|
let y = box.y1 + this._spacing;
|
||||||
|
|
||||||
|
for (let i = 0; i < children.length; i++) {
|
||||||
|
let childBox = new Clutter.ActorBox();
|
||||||
|
childBox.x1 = x;
|
||||||
|
childBox.y1 = y;
|
||||||
|
childBox.x2 = childBox.x1 + this._item_size;
|
||||||
|
childBox.y2 = childBox.y1 + this._item_size;
|
||||||
|
children[i].allocate(childBox, flags);
|
||||||
|
y += this._item_size + this._spacing;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
_onStyleChanged: function() {
|
||||||
|
let themeNode = this.actor.get_theme_node();
|
||||||
|
let [success, len] = themeNode.get_length('spacing', false);
|
||||||
|
if (success)
|
||||||
|
this._spacing = len;
|
||||||
|
[success, len] = themeNode.get_length('-shell-grid-item-size', false);
|
||||||
|
if (success)
|
||||||
|
this._item_size = len;
|
||||||
|
this._grid.queue_relayout();
|
||||||
|
},
|
||||||
|
|
||||||
|
removeAll: function () {
|
||||||
|
this._grid.get_children().forEach(Lang.bind(this, function (child) {
|
||||||
|
child.destroy();
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
addItem: function(actor) {
|
||||||
|
this._grid.add_actor(actor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(Dock.prototype);
|
||||||
|
|
||||||
|
function DockIcon(app, dock) {
|
||||||
|
this._init(app, dock);
|
||||||
|
}
|
||||||
|
|
||||||
|
DockIcon.prototype = {
|
||||||
|
_init : function(app, dock) {
|
||||||
|
this.app = app;
|
||||||
|
this.actor = new St.Button({ style_class: 'dock-app',
|
||||||
|
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
|
||||||
|
reactive: true,
|
||||||
|
x_fill: true,
|
||||||
|
y_fill: true });
|
||||||
|
this.actor._delegate = this;
|
||||||
|
this.actor.set_size(dockicon_size, dockicon_size);
|
||||||
|
|
||||||
|
this._icon = this.app.create_icon_texture(dockicon_size);
|
||||||
|
this.actor.set_child(this._icon);
|
||||||
|
|
||||||
|
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||||
|
|
||||||
|
this._menu = null;
|
||||||
|
this._menuManager = new PopupMenu.PopupMenuManager(this);
|
||||||
|
|
||||||
|
this._has_focus = false;
|
||||||
|
|
||||||
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
|
tracker.connect('notify::focus-app', Lang.bind(this, this._onStateChanged));
|
||||||
|
|
||||||
|
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
|
||||||
|
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||||
|
this.actor.connect('notify::hover', Lang.bind(this, this._hoverChanged));
|
||||||
|
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
this._stateChangedId = this.app.connect('notify::state',
|
||||||
|
Lang.bind(this, this._onStateChanged));
|
||||||
|
this._onStateChanged();
|
||||||
|
this._dock=dock;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onDestroy: function() {
|
||||||
|
if (this._stateChangedId > 0)
|
||||||
|
this.app.disconnect(this._stateChangedId);
|
||||||
|
this._stateChangedId = 0;
|
||||||
|
this._removeMenuTimeout();
|
||||||
|
},
|
||||||
|
|
||||||
|
_removeMenuTimeout: function() {
|
||||||
|
if (this._menuTimeoutId > 0) {
|
||||||
|
Mainloop.source_remove(this._menuTimeoutId);
|
||||||
|
this._menuTimeoutId = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_hoverChanged: function(actor) {
|
||||||
|
if (actor != this.actor)
|
||||||
|
this._has_focus = false;
|
||||||
|
else
|
||||||
|
this._has_focus = true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onStateChanged: function() {
|
||||||
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
|
let focusedApp = tracker.focus_app;
|
||||||
|
if (this.app.state != Shell.AppState.STOPPED) {
|
||||||
|
this.actor.add_style_class_name('running');
|
||||||
|
if (this.app == focusedApp) {
|
||||||
|
this.actor.add_style_class_name('focused');
|
||||||
|
} else {
|
||||||
|
this.actor.remove_style_class_name('focused');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.actor.remove_style_class_name('focused');
|
||||||
|
this.actor.remove_style_class_name('running');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onButtonPress: function(actor, event) {
|
||||||
|
let button = event.get_button();
|
||||||
|
if (button == 1) {
|
||||||
|
this._removeMenuTimeout();
|
||||||
|
this._menuTimeoutId = Mainloop.timeout_add(AppDisplay.MENU_POPUP_TIMEOUT, Lang.bind(this, function() {
|
||||||
|
this.popupMenu();
|
||||||
|
}));
|
||||||
|
} else if (button == 3) {
|
||||||
|
this.popupMenu();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_onClicked: function(actor, button) {
|
||||||
|
this._removeMenuTimeout();
|
||||||
|
|
||||||
|
if (button == 1) {
|
||||||
|
this._onActivate(Clutter.get_current_event());
|
||||||
|
} else if (button == 2) {
|
||||||
|
// Last workspace is always empty
|
||||||
|
let launchWorkspace = global.screen.get_workspace_by_index(global.screen.n_workspaces - 1);
|
||||||
|
launchWorkspace.activate(global.get_current_time());
|
||||||
|
this.emit('launching');
|
||||||
|
this.app.open_new_window(-1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
getId: function() {
|
||||||
|
return this.app.get_id();
|
||||||
|
},
|
||||||
|
|
||||||
|
popupMenu: function() {
|
||||||
|
this._removeMenuTimeout();
|
||||||
|
this.actor.fake_release();
|
||||||
|
|
||||||
|
this._dock._disableHideDock();
|
||||||
|
|
||||||
|
if (!this._menu) {
|
||||||
|
this._menu = new DockIconMenu(this);
|
||||||
|
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
|
||||||
|
this.activateWindow(window);
|
||||||
|
}));
|
||||||
|
this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) {
|
||||||
|
if (!isPoppedUp){
|
||||||
|
//Restore value of autohidedock
|
||||||
|
this._dock._restoreHideDock();
|
||||||
|
this._dock._hideDock();
|
||||||
|
|
||||||
|
this._onMenuPoppedDown();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
this._menuManager.addMenu(this._menu, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._menu.popup();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
activateWindow: function(metaWindow) {
|
||||||
|
if (metaWindow) {
|
||||||
|
this._didActivateWindow = true;
|
||||||
|
Main.activateWindow(metaWindow);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setSelected: function (isSelected) {
|
||||||
|
this._selected = isSelected;
|
||||||
|
if (this._selected)
|
||||||
|
this.actor.add_style_class_name('selected');
|
||||||
|
else
|
||||||
|
this.actor.remove_style_class_name('selected');
|
||||||
|
},
|
||||||
|
|
||||||
|
_onMenuPoppedDown: function() {
|
||||||
|
this.actor.sync_hover();
|
||||||
|
},
|
||||||
|
|
||||||
|
_getRunning: function() {
|
||||||
|
return this.app.state != Shell.AppState.STOPPED;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onActivate: function (event) {
|
||||||
|
this.emit('launching');
|
||||||
|
let modifiers = Shell.get_event_state(event);
|
||||||
|
|
||||||
|
if (modifiers & Clutter.ModifierType.CONTROL_MASK
|
||||||
|
&& this.app.state == Shell.AppState.RUNNING) {
|
||||||
|
let current_workspace = global.screen.get_active_workspace().index();
|
||||||
|
this.app.open_new_window(current_workspace);
|
||||||
|
} else {
|
||||||
|
let tracker = Shell.WindowTracker.get_default();
|
||||||
|
let focusedApp = tracker.focus_app;
|
||||||
|
|
||||||
|
if (this.app == focusedApp) {
|
||||||
|
let windows = this.app.get_windows();
|
||||||
|
let current_workspace = global.screen.get_active_workspace();
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
let w = windows[i];
|
||||||
|
if (w.get_workspace() == current_workspace)
|
||||||
|
w.minimize();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.app.activate(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Main.overview.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
shellWorkspaceLaunch : function() {
|
||||||
|
this.app.open_new_window();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Signals.addSignalMethods(DockIcon.prototype);
|
||||||
|
|
||||||
|
function DockIconMenu(source) {
|
||||||
|
this._init(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
DockIconMenu.prototype = {
|
||||||
|
__proto__: AppDisplay.AppIconMenu.prototype,
|
||||||
|
|
||||||
|
_init: function(source) {
|
||||||
|
switch (position) {
|
||||||
|
case PositionMode.LEFT:
|
||||||
|
PopupMenu.PopupMenu.prototype._init.call(this, source.actor, St.Align.MIDDLE, St.Side.LEFT, 0);
|
||||||
|
break;
|
||||||
|
case PositionMode.RIGHT:
|
||||||
|
default:
|
||||||
|
PopupMenu.PopupMenu.prototype._init.call(this, source.actor, St.Align.MIDDLE, St.Side.RIGHT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._source = source;
|
||||||
|
|
||||||
|
this.connect('activate', Lang.bind(this, this._onActivate));
|
||||||
|
|
||||||
|
this.actor.add_style_class_name('dock-menu');
|
||||||
|
|
||||||
|
// Chain our visibility and lifecycle to that of the source
|
||||||
|
source.actor.connect('notify::mapped', Lang.bind(this, function () {
|
||||||
|
if (!source.actor.mapped)
|
||||||
|
this.close();
|
||||||
|
}));
|
||||||
|
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
|
||||||
|
|
||||||
|
Main.layoutManager.addChrome(this.actor);
|
||||||
|
},
|
||||||
|
|
||||||
|
_redisplay: function() {
|
||||||
|
this.removeAll();
|
||||||
|
|
||||||
|
let windows = this._source.app.get_windows();
|
||||||
|
|
||||||
|
// Display the app windows menu items and the separator between windows
|
||||||
|
// of the current desktop and other windows.
|
||||||
|
let activeWorkspace = global.screen.get_active_workspace();
|
||||||
|
let separatorShown = windows.length > 0 && windows[0].get_workspace() != activeWorkspace;
|
||||||
|
|
||||||
|
for (let i = 0; i < windows.length; i++) {
|
||||||
|
if (!separatorShown && windows[i].get_workspace() != activeWorkspace) {
|
||||||
|
this._appendSeparator();
|
||||||
|
separatorShown = true;
|
||||||
|
}
|
||||||
|
let item = this._appendMenuItem(windows[i].title);
|
||||||
|
item._window = windows[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (windows.length > 0)
|
||||||
|
this._appendSeparator();
|
||||||
|
|
||||||
|
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
|
||||||
|
|
||||||
|
this._newWindowMenuItem = windows.length > 0 ? this._appendMenuItem(_("New Window")) : null;
|
||||||
|
|
||||||
|
this._quitAppMenuItem = windows.length >0 ? this._appendMenuItem(_("Quit Application")) : null;
|
||||||
|
|
||||||
|
if (windows.length > 0)
|
||||||
|
this._appendSeparator();
|
||||||
|
this._toggleFavoriteMenuItem = this._appendMenuItem(isFavorite ?
|
||||||
|
_("Remove from Favorites")
|
||||||
|
: _("Add to Favorites"));
|
||||||
|
|
||||||
|
this._highlightedItem = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onActivate: function (actor, child) {
|
||||||
|
if (child._window) {
|
||||||
|
let metaWindow = child._window;
|
||||||
|
this.emit('activate-window', metaWindow);
|
||||||
|
} else if (child == this._newWindowMenuItem) {
|
||||||
|
let current_workspace = global.screen.get_active_workspace().index();
|
||||||
|
this._source.app.open_new_window(current_workspace);
|
||||||
|
this.emit('activate-window', null);
|
||||||
|
} else if (child == this._quitAppMenuItem) {
|
||||||
|
this._source.app.request_quit();
|
||||||
|
} else if (child == this._toggleFavoriteMenuItem) {
|
||||||
|
let favs = AppFavorites.getAppFavorites();
|
||||||
|
let isFavorite = favs.isFavorite(this._source.app.get_id());
|
||||||
|
if (isFavorite)
|
||||||
|
favs.removeFavorite(this._source.app.get_id());
|
||||||
|
else
|
||||||
|
favs.addFavorite(this._source.app.get_id());
|
||||||
|
}
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(extensionMeta) {
|
||||||
|
imports.gettext.bindtextdomain('gnome-shell-extensions', GLib.build_filenamev([metadata.path, 'locale']));
|
||||||
|
}
|
||||||
|
|
||||||
|
let dock;
|
||||||
|
|
||||||
|
function enable() {
|
||||||
|
dock = new Dock();
|
||||||
|
}
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
dock.destroy();
|
||||||
|
dock = null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"uuid": "@uuid@",
|
||||||
|
"name": "Dock",
|
||||||
|
"description": "A dock for the GNOME Shell -- displays favorite and running applications",
|
||||||
|
"original-author": "tclaesson@gmail.com",
|
||||||
|
"shell-version": [ "@shell_current@", "3.2" ],
|
||||||
|
"url": "@url@"
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<schemalist gettext-domain="gnome-shell-extensions">
|
||||||
|
<enum id='org.gnome.shell.extensions.dock.PositionMode'>
|
||||||
|
<value nick='left' value='0'/>
|
||||||
|
<value nick='right' value='1'/>
|
||||||
|
</enum>
|
||||||
|
<enum id='org.gnome.shell.extensions.dock.AutoHideEffect'>
|
||||||
|
<value nick='resize' value='0'/>
|
||||||
|
<value nick='rescale' value='1'/>
|
||||||
|
<value nick='move' value='2'/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<schema id="org.gnome.shell.extensions.dock" path="/org/gnome/shell/extensions/dock/">
|
||||||
|
<key name="position" enum="org.gnome.shell.extensions.dock.PositionMode">
|
||||||
|
<default>'right'</default>
|
||||||
|
<_summary>Position of the dock</_summary>
|
||||||
|
<_description>Sets the position of the dock in the screen. Allowed values are 'right' or 'left'</_description>
|
||||||
|
</key>
|
||||||
|
<key name="size" type="i">
|
||||||
|
<default>48</default>
|
||||||
|
<_summary>Icon size</_summary>
|
||||||
|
<_description>Sets icon size of the dock.</_description>
|
||||||
|
</key>
|
||||||
|
<key name="autohide" type="b">
|
||||||
|
<default>true</default>
|
||||||
|
<_summary>Enable/disable autohide</_summary>
|
||||||
|
</key>
|
||||||
|
<key name="hide-effect" enum="org.gnome.shell.extensions.dock.AutoHideEffect">
|
||||||
|
<default>'resize'</default>
|
||||||
|
<_summary>Autohide effect</_summary>
|
||||||
|
<_description>Sets the effect of the hide dock. Allowed values are 'resize' or 'rescale'</_description>
|
||||||
|
</key>
|
||||||
|
<key name="hide-effect-duration" type="d">
|
||||||
|
<default>0.3</default>
|
||||||
|
<_summary>Autohide duration</_summary>
|
||||||
|
<_description>Sets the time duration of the autohide effect.</_description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#dock {
|
||||||
|
border-radius: 9px;
|
||||||
|
background-color: rgba(0,0,0,0.9);
|
||||||
|
border-width: 2px;
|
||||||
|
border-color: #5f5f5f;
|
||||||
|
}
|
||||||
|
/* Panel */
|
||||||
|
.dock-app {
|
||||||
|
padding: 4px;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition-duration: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dock-app.running {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #181818;
|
||||||
|
background-gradient-direction: vertical;
|
||||||
|
background-gradient-start: #3d3d3d;
|
||||||
|
background-gradient-end: #181818;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dock-app.selected {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dock-app.focused {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #5f5f5f;
|
||||||
|
background-gradient-direction: vertical;
|
||||||
|
background-gradient-start: rgba(61,61,61,0.8);
|
||||||
|
background-gradient-end: rgba(24,24,24,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dock-app:hover {
|
||||||
|
padding: 3px;
|
||||||
|
border: 1px solid #666666;
|
||||||
|
background-gradient-direction: vertical;
|
||||||
|
background-gradient-start: rgba(61,61,61,0.8);
|
||||||
|
background-gradient-end: rgba(24,24,24,0.2);
|
||||||
|
transition-duration: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dock-app:active {
|
||||||
|
padding: 3px;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
border: 1px solid #5f5f5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dock-menu {
|
||||||
|
font-size: 12px
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
EXTENSION_ID = drive-menu
|
||||||
|
|
||||||
|
include ../../extension.mk
|
||||||
@@ -1,231 +1,106 @@
|
|||||||
/* exported init enable disable */
|
|
||||||
// Drive menu extension
|
// Drive menu extension
|
||||||
const {Clutter, Gio, GObject, Shell, St} = imports.gi;
|
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 ExtensionUtils = imports.misc.extensionUtils;
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
|
const Panel = imports.ui.panel;
|
||||||
const PanelMenu = imports.ui.panelMenu;
|
const PanelMenu = imports.ui.panelMenu;
|
||||||
const PopupMenu = imports.ui.popupMenu;
|
const PopupMenu = imports.ui.popupMenu;
|
||||||
const ShellMountOperation = imports.ui.shellMountOperation;
|
|
||||||
|
|
||||||
const _ = ExtensionUtils.gettext;
|
function DriveMenuItem(place) {
|
||||||
|
this._init(place);
|
||||||
Gio._promisify(Gio.File.prototype, 'query_filesystem_info_async');
|
|
||||||
|
|
||||||
class MountMenuItem extends PopupMenu.PopupBaseMenuItem {
|
|
||||||
static {
|
|
||||||
GObject.registerClass(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(mount) {
|
|
||||||
super({
|
|
||||||
style_class: 'drive-menu-item',
|
|
||||||
});
|
|
||||||
|
|
||||||
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.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,
|
|
||||||
style_class: 'button',
|
|
||||||
});
|
|
||||||
ejectButton.connect('clicked', this._eject.bind(this));
|
|
||||||
this.add(ejectButton);
|
|
||||||
|
|
||||||
this.hide();
|
|
||||||
|
|
||||||
this._changedId = mount.connect('changed', this._syncVisibility.bind(this));
|
|
||||||
this._syncVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDestroy() {
|
|
||||||
if (this._changedId) {
|
|
||||||
this.mount.disconnect(this._changedId);
|
|
||||||
this._changedId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
async _isInteresting() {
|
|
||||||
if (!this.mount.can_eject() && !this.mount.can_unmount())
|
|
||||||
return false;
|
|
||||||
if (this.mount.is_shadowed())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
let volume = this.mount.get_volume();
|
|
||||||
|
|
||||||
if (volume)
|
|
||||||
return volume.get_identifier('class') !== 'network';
|
|
||||||
|
|
||||||
const root = this.mount.get_root();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const attr = Gio.FILE_ATTRIBUTE_FILESYSTEM_REMOTE;
|
|
||||||
const info = await root.query_filesystem_info_async(attr, null);
|
|
||||||
return !info.get_attribute_boolean(attr);
|
|
||||||
} catch (e) {
|
|
||||||
log(`Failed to query filesystem: ${e.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hack, fall back to looking at GType
|
|
||||||
return Gio._LocalFilePrototype.isPrototypeOf(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _syncVisibility() {
|
|
||||||
this.visible = await this._isInteresting();
|
|
||||||
}
|
|
||||||
|
|
||||||
_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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_unmountFinish(mount, result) {
|
|
||||||
try {
|
|
||||||
mount.unmount_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(exception) {
|
|
||||||
// TRANSLATORS: %s is the filesystem name
|
|
||||||
let msg = _('Ejecting drive “%s” failed:').format(this.mount.get_name());
|
|
||||||
Main.notifyError(msg, exception.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(uri, context);
|
|
||||||
|
|
||||||
super.activate(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DriveMenu extends PanelMenu.Button {
|
DriveMenuItem.prototype = {
|
||||||
static {
|
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
|
||||||
GObject.registerClass(this);
|
|
||||||
|
_init: function(place) {
|
||||||
|
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
|
||||||
|
|
||||||
|
this.place = place;
|
||||||
|
|
||||||
|
this.label = new St.Label({ text: place.name });
|
||||||
|
this.addActor(this.label);
|
||||||
|
|
||||||
|
let ejectIcon = new St.Icon({ icon_name: 'media-eject',
|
||||||
|
icon_type: St.IconType.SYMBOLIC,
|
||||||
|
style_class: 'popup-menu-icon ' });
|
||||||
|
let ejectButton = new St.Button({ child: ejectIcon });
|
||||||
|
ejectButton.connect('clicked', Lang.bind(this, this._eject));
|
||||||
|
this.addActor(ejectButton);
|
||||||
|
},
|
||||||
|
|
||||||
|
_eject: function() {
|
||||||
|
this.place.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
activate: function(event) {
|
||||||
|
this.place.launch({ timestamp: event.get_time() });
|
||||||
|
|
||||||
|
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this, event);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
constructor() {
|
function DriveMenu() {
|
||||||
super(0.5, _('Removable devices'));
|
this._init();
|
||||||
|
|
||||||
let icon = new St.Icon({
|
|
||||||
icon_name: 'media-eject-symbolic',
|
|
||||||
style_class: 'system-status-icon',
|
|
||||||
});
|
|
||||||
|
|
||||||
this.add_child(icon);
|
|
||||||
|
|
||||||
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._mounts = [];
|
|
||||||
|
|
||||||
this._monitor.get_mounts().forEach(this._addMount.bind(this));
|
|
||||||
|
|
||||||
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._updateMenuVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateMenuVisibility() {
|
|
||||||
if (this._mounts.filter(i => i.visible).length > 0)
|
|
||||||
this.show();
|
|
||||||
else
|
|
||||||
this.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
_addMount(mount) {
|
|
||||||
let item = new MountMenuItem(mount);
|
|
||||||
this._mounts.unshift(item);
|
|
||||||
this.menu.addMenuItem(item, 0);
|
|
||||||
|
|
||||||
item.connect('notify::visible', () => this._updateMenuVisibility());
|
|
||||||
}
|
|
||||||
|
|
||||||
_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');
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDestroy() {
|
|
||||||
if (this._addedId) {
|
|
||||||
this._monitor.disconnect(this._addedId);
|
|
||||||
this._monitor.disconnect(this._removedId);
|
|
||||||
this._addedId = 0;
|
|
||||||
this._removedId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
super._onDestroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
DriveMenu.prototype = {
|
||||||
function init() {
|
__proto__: PanelMenu.SystemStatusButton.prototype,
|
||||||
ExtensionUtils.initTranslations();
|
|
||||||
|
_init: function() {
|
||||||
|
// is 'media-eject' better?
|
||||||
|
PanelMenu.SystemStatusButton.prototype._init.call(this, 'media-optical');
|
||||||
|
|
||||||
|
this._manager = Main.placesManager;
|
||||||
|
this._manager.connect('mounts-updated', Lang.bind(this, this._update));
|
||||||
|
|
||||||
|
this._contentSection = new PopupMenu.PopupMenuSection();
|
||||||
|
this.menu.addMenuItem(this._contentSection);
|
||||||
|
|
||||||
|
this._update();
|
||||||
|
|
||||||
|
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||||
|
this.menu.addAction(_("Open file manager"), function(event) {
|
||||||
|
let appSystem = Shell.AppSystem.get_default();
|
||||||
|
let app = appSystem.lookup_app('nautilus.desktop');
|
||||||
|
app.activate_full(-1, event.get_time());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_update: function() {
|
||||||
|
this._contentSection.removeAll();
|
||||||
|
|
||||||
|
let mounts = this._manager.getMounts();
|
||||||
|
let any = false;
|
||||||
|
for (let i = 0; i < mounts.length; i++) {
|
||||||
|
if (mounts[i].isRemovable()) {
|
||||||
|
this._contentSection.addMenuItem(new DriveMenuItem(mounts[i]));
|
||||||
|
any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actor.visible = any;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put your extension initialization code here
|
||||||
|
function init(metadata) {
|
||||||
|
imports.gettext.bindtextdomain('gnome-shell-extensions', GLib.build_filenamev([metadata.path, 'locale']));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _indicator;
|
let _indicator;
|
||||||
|
|
||||||
/** */
|
|
||||||
function enable() {
|
function enable() {
|
||||||
_indicator = new DriveMenu();
|
_indicator = new DriveMenu;
|
||||||
Main.panel.addToStatusArea('drive-menu', _indicator);
|
Main.panel.addToStatusArea('drive-menu', _indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
function disable() {
|
function disable() {
|
||||||
_indicator.destroy();
|
_indicator.destroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
extension_data += configure_file(
|
|
||||||
input: metadata_name + '.in',
|
|
||||||
output: metadata_name,
|
|
||||||
configuration: metadata_conf
|
|
||||||
)
|
|
||||||
extension_data += files('stylesheet.css')
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user