Compare commits
186 Commits
3.31.91
...
wip/jimmac
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6393e90a5a | ||
![]() |
4e5ca6d376 | ||
![]() |
2fab75f448 | ||
![]() |
22883f2fa2 | ||
![]() |
5d9f80bc73 | ||
![]() |
f7d117488b | ||
![]() |
244a329ee7 | ||
![]() |
044572cb60 | ||
![]() |
746875258d | ||
![]() |
4892a87dfe | ||
![]() |
8b9c8ddb1e | ||
![]() |
eb9000576c | ||
![]() |
862aaf341e | ||
![]() |
a5c75ff58b | ||
![]() |
4541fb9819 | ||
![]() |
9f8edd980c | ||
![]() |
e5b9043435 | ||
![]() |
c0012c2ea4 | ||
![]() |
b77e4975f0 | ||
![]() |
e83f2344f6 | ||
![]() |
de6512be1a | ||
![]() |
0b72ff1896 | ||
![]() |
fea0192772 | ||
![]() |
f81ac498fb | ||
![]() |
5357e0a18c | ||
![]() |
d7632bbd3d | ||
![]() |
1b5e91e4b3 | ||
![]() |
727195c767 | ||
![]() |
9158f55360 | ||
![]() |
8146e9d527 | ||
![]() |
4247251020 | ||
![]() |
7eee0e0ed6 | ||
![]() |
4f0851ca77 | ||
![]() |
911ae49767 | ||
![]() |
5af81d4057 | ||
![]() |
c435889baa | ||
![]() |
49f79d9d5d | ||
![]() |
1767cd0f6c | ||
![]() |
3e0915521a | ||
![]() |
a298943fac | ||
![]() |
df9ddf96a5 | ||
![]() |
4fa5d701d5 | ||
![]() |
b05683d586 | ||
![]() |
2f3f3fbcdb | ||
![]() |
611605a67f | ||
![]() |
0427a782be | ||
![]() |
32baff5906 | ||
![]() |
0089143d06 | ||
![]() |
05e55cee23 | ||
![]() |
31e7f0340f | ||
![]() |
6e317a54fd | ||
![]() |
9c1f62c38c | ||
![]() |
1341d5557f | ||
![]() |
b7d79a5f06 | ||
![]() |
62233a4db4 | ||
![]() |
4a7e2ddff5 | ||
![]() |
fb737ebde0 | ||
![]() |
bf77cb44e7 | ||
![]() |
c72e2bb4a9 | ||
![]() |
68c182b1df | ||
![]() |
348d303794 | ||
![]() |
ede0fd8660 | ||
![]() |
187c2193e8 | ||
![]() |
706bdd8059 | ||
![]() |
436861edc8 | ||
![]() |
9729a2e772 | ||
![]() |
6b924c00c5 | ||
![]() |
b90f4d29a4 | ||
![]() |
47915f8c11 | ||
![]() |
5dfdeaa4ea | ||
![]() |
98a2a81f2a | ||
![]() |
c4850027bc | ||
![]() |
d4202e7f38 | ||
![]() |
4f65283f31 | ||
![]() |
d86d3bbe54 | ||
![]() |
6f794738e8 | ||
![]() |
ef7a93bb07 | ||
![]() |
5197a992a6 | ||
![]() |
49d8540f6d | ||
![]() |
6e1a1f1a57 | ||
![]() |
c73428247c | ||
![]() |
fc2caf5794 | ||
![]() |
b117826ada | ||
![]() |
26b44b48ab | ||
![]() |
6349f0feb1 | ||
![]() |
2ae17cfb50 | ||
![]() |
4785093a5c | ||
![]() |
859aef78c4 | ||
![]() |
20730a5465 | ||
![]() |
fc5f687afc | ||
![]() |
53e56f2395 | ||
![]() |
da314aff79 | ||
![]() |
fe89f7c5ac | ||
![]() |
8b3be5e063 | ||
![]() |
58dc538510 | ||
![]() |
6cbef9355d | ||
![]() |
22eac5c508 | ||
![]() |
a2860e9c73 | ||
![]() |
1c5258ab68 | ||
![]() |
8641eaa538 | ||
![]() |
88436383c0 | ||
![]() |
affdcdcb0e | ||
![]() |
06174be777 | ||
![]() |
fde8401124 | ||
![]() |
70ac33d58c | ||
![]() |
5a897407d9 | ||
![]() |
1b3c26364b | ||
![]() |
ae07aa7864 | ||
![]() |
fb80831269 | ||
![]() |
561cecf383 | ||
![]() |
60ccdc2deb | ||
![]() |
d7d996b1d3 | ||
![]() |
32b8bc39ac | ||
![]() |
9dc99ad611 | ||
![]() |
628cb4d553 | ||
![]() |
ad80bce78d | ||
![]() |
1c9d821aa2 | ||
![]() |
510b060947 | ||
![]() |
26e33ff093 | ||
![]() |
5f2bd70690 | ||
![]() |
6dfa550663 | ||
![]() |
252e2420ad | ||
![]() |
572d54981e | ||
![]() |
61471f9fb4 | ||
![]() |
4d0a742d64 | ||
![]() |
5f4e0e5ff8 | ||
![]() |
a4c159ecad | ||
![]() |
b1f893e998 | ||
![]() |
789dc165af | ||
![]() |
115eda9650 | ||
![]() |
d027e35cef | ||
![]() |
b3e178af9d | ||
![]() |
559ec8750a | ||
![]() |
02c3980b83 | ||
![]() |
6f027ee7dc | ||
![]() |
6d6c2e5b99 | ||
![]() |
4a4f752459 | ||
![]() |
8f1fff1374 | ||
![]() |
deead2af97 | ||
![]() |
9e881ab637 | ||
![]() |
b6ec02cef2 | ||
![]() |
26e3ccda49 | ||
![]() |
2bda79cb3a | ||
![]() |
19c60ff5c5 | ||
![]() |
e3c5c9a2e7 | ||
![]() |
2c17c186b8 | ||
![]() |
ef1697d00d | ||
![]() |
40e7638a4b | ||
![]() |
aaf69b2898 | ||
![]() |
0464361ca5 | ||
![]() |
420697693b | ||
![]() |
37f53a42da | ||
![]() |
5617ffc79c | ||
![]() |
ca4d86e9e5 | ||
![]() |
0141fef561 | ||
![]() |
5d4a804c90 | ||
![]() |
6bc3300e5a | ||
![]() |
15f69bdc3b | ||
![]() |
0bcf76970a | ||
![]() |
03c4628cad | ||
![]() |
9f4ae9618a | ||
![]() |
3590af15bb | ||
![]() |
c5de7fd20e | ||
![]() |
7127fb1fa1 | ||
![]() |
7cf11abefc | ||
![]() |
d78b416e1a | ||
![]() |
f5144ec899 | ||
![]() |
08d1ebe7ee | ||
![]() |
a665801e9f | ||
![]() |
112e3b110b | ||
![]() |
94a674c008 | ||
![]() |
72be8eeb31 | ||
![]() |
ad8690bb2e | ||
![]() |
76cb08a72a | ||
![]() |
2d4989e937 | ||
![]() |
f248b91f82 | ||
![]() |
d671eb1969 | ||
![]() |
70f4906ca5 | ||
![]() |
ffb9aa1ace | ||
![]() |
823fd855cf | ||
![]() |
f5ee225362 | ||
![]() |
ff1ea4b1c9 | ||
![]() |
779b5afa51 | ||
![]() |
6d870f6ae4 | ||
![]() |
d3926cbca9 | ||
![]() |
a308804679 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -80,3 +80,4 @@ tests/run-test.sh
|
||||
*~
|
||||
*.patch
|
||||
*.sw?
|
||||
.vscode
|
||||
|
@@ -1,32 +1,86 @@
|
||||
stages:
|
||||
- review
|
||||
- source_check
|
||||
- build
|
||||
- test
|
||||
|
||||
variables:
|
||||
JS_LOG: "js-report.txt"
|
||||
POT_LOG: "pot-update.txt"
|
||||
|
||||
.only_default: &only_default
|
||||
only:
|
||||
- branches
|
||||
- tags
|
||||
- merge_requests
|
||||
|
||||
check_commit_log:
|
||||
image: registry.fedoraproject.org/fedora:latest
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v1
|
||||
stage: review
|
||||
before_script:
|
||||
- dnf install -y git
|
||||
script:
|
||||
- ./.gitlab-ci/check-commit-log.sh
|
||||
only:
|
||||
- merge_requests
|
||||
|
||||
js_check:
|
||||
image: registry.fedoraproject.org/fedora:latest
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
|
||||
stage: source_check
|
||||
before_script:
|
||||
- dnf install -y findutils mozjs60-devel
|
||||
script:
|
||||
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
|
||||
- (! grep -q . $JS_LOG)
|
||||
<<: *only_default
|
||||
only:
|
||||
changes:
|
||||
- js/**/*
|
||||
artifacts:
|
||||
paths:
|
||||
- ${JS_LOG}
|
||||
when: on_failure
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
build:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/master:v1
|
||||
stage: build
|
||||
before_script:
|
||||
- .gitlab-ci/checkout-mutter.sh
|
||||
- meson mutter mutter/build --prefix=/usr -Dtests=false
|
||||
- ninja -C mutter/build install
|
||||
script:
|
||||
- meson . build -Dbuiltype=debugoptimized
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
<<: *only_default
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- mutter
|
||||
- build
|
||||
|
||||
test:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/master:v1
|
||||
stage: test
|
||||
before_script:
|
||||
- ninja -C mutter/build install
|
||||
script:
|
||||
- xvfb-run meson test -C build --no-rebuild
|
||||
<<: *only_default
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- build/meson-logs/testlog.txt
|
||||
when: on_failure
|
||||
|
||||
test-pot:
|
||||
image: registry.gitlab.gnome.org/gnome/gnome-shell/master:v1
|
||||
stage: test
|
||||
before_script:
|
||||
- ninja -C mutter/build install
|
||||
script:
|
||||
# Check that pot files are generated correctly:
|
||||
# https://savannah.gnu.org/bugs/?50920#comment5
|
||||
- ninja -C build gnome-shell-pot 2>&1 | awk '
|
||||
BEGIN { start=0; }
|
||||
start==1 { print $0; }
|
||||
/gnome-shell-pot/ { start=1; }
|
||||
' | tee $POT_LOG
|
||||
- (! grep -q . $POT_LOG)
|
||||
<<: *only_default
|
||||
|
19
.gitlab-ci/Dockerfile
Normal file
19
.gitlab-ci/Dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
FROM registry.gitlab.gnome.org/gnome/mutter/master:v1
|
||||
|
||||
RUN dnf -y update && dnf -y upgrade && \
|
||||
dnf install -y 'dnf-command(copr)' && \
|
||||
dnf copr enable -y fmuellner/gnome-shell-ci && \
|
||||
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
|
||||
|
||||
# bt only exports HAVE_BLUETOOTH to js, rest are outdated build-requires
|
||||
dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel \
|
||||
upower-devel python3-devel && \
|
||||
|
||||
# We'll build mutter ourselves
|
||||
dnf remove -y --noautoremove mutter mutter-devel && \
|
||||
|
||||
# Needed for tests
|
||||
dnf install -y '*/xvfb-run' gdm-lib accountsservice-libs && \
|
||||
|
||||
dnf clean all && \
|
||||
rm -rf /var/cache/dnf
|
18
.gitlab-ci/Dockerfile.extension-ci
Normal file
18
.gitlab-ci/Dockerfile.extension-ci
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM registry.fedoraproject.org/fedora:latest
|
||||
|
||||
RUN dnf -y update && dnf -y upgrade && \
|
||||
dnf install -y 'dnf-command(copr)' && \
|
||||
|
||||
# For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'`
|
||||
dnf install -y findutils mozjs60-devel && \
|
||||
|
||||
# For static analysis with eslint
|
||||
dnf install -y nodejs && \
|
||||
npm install -g eslint && \
|
||||
|
||||
# Shameless plug for my own tooling; useful for generating zip
|
||||
dnf copr enable -y fmuellner/gnome-shell-ci && \
|
||||
dnf install -y gnome-extensions-tool meson && \
|
||||
|
||||
dnf clean all && \
|
||||
rm -rf /var/cache/dnf
|
@@ -11,9 +11,21 @@ branch_point=$(git merge-base HEAD FETCH_HEAD)
|
||||
|
||||
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
|
||||
|
||||
test -z "$commits" && { echo Commit range empty; exit 1; }
|
||||
if [ -z "$commits" ]; then
|
||||
echo Commit range empty
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function commit_message_has_url() {
|
||||
commit=$1
|
||||
commit_message=$(git show -s --format='format:%b' $commit)
|
||||
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
|
||||
return $?
|
||||
}
|
||||
|
||||
for commit in $commits; do
|
||||
git show -s --format='format:%b' $commit | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)" ||
|
||||
{ echo "Missing merge request or issue URL on commit $(echo $commit | cut -c -8)"; exit 1; }
|
||||
if ! commit_message_has_url $commit; then
|
||||
echo "Missing merge request or issue URL on commit $(echo $commit | cut -c -8)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
31
.gitlab-ci/checkout-mutter.sh
Executable file
31
.gitlab-ci/checkout-mutter.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
shell_branch=$(git describe --contains --all HEAD)
|
||||
mutter_target=
|
||||
|
||||
git clone https://gitlab.gnome.org/GNOME/mutter.git
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo Checkout failed
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd mutter
|
||||
|
||||
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//gnome-shell/mutter}
|
||||
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
||||
|
||||
echo Looking for $merge_request_branch on remote ...
|
||||
if git fetch $merge_request_remote $merge_request_branch >/dev/null 2>&1; then
|
||||
mutter_target=FETCH_HEAD
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$mutter_target" ]; then
|
||||
mutter_target=$(git branch -r -l $shell_branch)
|
||||
mutter_target=${mutter_target:-origin/master}
|
||||
echo Using $mutter_target instead
|
||||
fi
|
||||
|
||||
git checkout $mutter_target
|
41
NEWS
41
NEWS
@@ -1,3 +1,44 @@
|
||||
3.32.0
|
||||
======
|
||||
* Fix sizing issues in on-screen-keyboard emoji panel [Carlos; !439]
|
||||
* Fix test linker failure on Debian/Ubuntu [Iain; !442]
|
||||
* Avoid assertion when sizing fallback app icons from CSS [Florian; #1027]
|
||||
* Fix mis-sized menu arrows after texture cache changes [Florian; !452]
|
||||
|
||||
Contributors:
|
||||
Carlos Garnacho, Iain Lane, Florian Müllner
|
||||
|
||||
Translators:
|
||||
Gábor Kelemen [hu], Victor Ibragimov [tg], Ryuta Fujii [ja], Piotr Drąg [af,
|
||||
tg], Mart Raudsepp [et]
|
||||
|
||||
3.31.92
|
||||
=======
|
||||
* Fix visual glitch in submenus [Alex; #987]
|
||||
* Support fractional scaling [Jonas, Marco; #765011, !5]
|
||||
* Only consider visible children for :first-child/:last-child [Florian; !312]
|
||||
* Hide trailing separator in search results [verdre; !311]
|
||||
* Remember choice in inhibit-shortcuts dialogue [Olivier; !382]
|
||||
* Don't toggle on-screen keyboard on every focus change [Carlos; !397]
|
||||
* Fix legacy tray icons not responding to events on wayland [Florian; #191]
|
||||
* Fix generating French OSK layout [Florian; #997]
|
||||
* Use borderless round user images [Florian; #811]
|
||||
* Misc. bug fixes and cleanups [Andrea, Robert, Florian, Marco, Niels,
|
||||
Benjamin; !414, !417, !420, #996, !408, !422, !425, #1006, !427, !315,
|
||||
#989, !430, !431, !432, #1015, !429, !423, !419, !434]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Alan, Andrea Azzarone, Benjamin Berg, Olivier Fourdan,
|
||||
Carlos Garnacho, Niels De Graef, Robert Mader, Alex Monday, Florian Müllner,
|
||||
Marco Trevisan (Treviño), verdre
|
||||
|
||||
Translators:
|
||||
Carmen Bianca BAKKER [eo], Asier Sarasua Garmendia [eu], Stas Solovey [ru],
|
||||
Changwoo Ryu [ko], Julien Humbert [fr], Milo Casagrande [it],
|
||||
Марко Костић [sr], Ask Hjorth Larsen [da], Kukuh Syafaat [id],
|
||||
Daniel Șerbănescu [ro], Bernd Homuth [de], Trần Ngọc Quân [vi],
|
||||
Nathan Follens [nl], Rūdolfs Mazurs [lv], Aurimas Černius [lt]
|
||||
|
||||
3.31.91
|
||||
=======
|
||||
* Don't close on-screen-keyboard's language menu on hover [Florian; #171]
|
||||
|
40
README.mdwn
Normal file
40
README.mdwn
Normal file
@@ -0,0 +1,40 @@
|
||||
cldr2json
|
||||
=========
|
||||
|
||||
This script converts Unicode CLDR android keyboard layouts to JSON usable by
|
||||
GNOME Shell.
|
||||
|
||||
CLDR keyboard layouts can be found at
|
||||
<http://www.unicode.org/Public/cldr/latest/keyboards.zip>
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
./cldr2json <input file or directory> <output directory>
|
||||
|
||||
example:
|
||||
|
||||
./cldr2json cldr/keyboards/android/ json_layouts/
|
||||
|
||||
|
||||
Keyboard layout mapping
|
||||
=======================
|
||||
|
||||
Unicode CLDR layout identifiers are language codes, while XKB layout
|
||||
identifiers are... something else. The mapping between the two currently uses
|
||||
heuristic based on the layout descriptions, in this order:
|
||||
|
||||
- if the CLDR layout description matches an XKB layout description, chose its
|
||||
XKB identifier
|
||||
- if one word of the CLDR layout description matches an XKB layout
|
||||
description, chose its XKB identifier
|
||||
- if the CLDR layout description matches one word of an XKB layout description,
|
||||
chose its XKB identifier
|
||||
|
||||
That doesn't always work. For instance it fails for "en" language, that should
|
||||
match "us" XKB identifier. For such cases, there is a mapping in
|
||||
LOCALE_TO_XKB_OVERRIDES at the top of the script. If you discover a weird
|
||||
mapping of if you get a "failed to find XKB mapping for <locale>" warning then
|
||||
please consider adding an override there.
|
||||
|
208
cldr2json.py
Executable file
208
cldr2json.py
Executable file
@@ -0,0 +1,208 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright 2015 Daiki Ueno <dueno@src.gnome.org>
|
||||
# 2016 Parag Nemade <pnemade@redhat.com>
|
||||
# 2017 Alan <alan@boum.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This 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
|
||||
# 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, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
import glob
|
||||
import json
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree
|
||||
|
||||
import gi
|
||||
gi.require_version('GnomeDesktop', '3.0') # NOQA: E402
|
||||
from gi.repository import GnomeDesktop
|
||||
|
||||
ESCAPE_PATTERN = re.compile(r'\\u\{([0-9A-Fa-f]+?)\}')
|
||||
ISO_PATTERN = re.compile(r'[A-E]([0-9]+)')
|
||||
|
||||
LOCALE_TO_XKB_OVERRIDES = {
|
||||
'af': 'za',
|
||||
'en': 'us',
|
||||
'en-GB': 'uk',
|
||||
'es-US': 'latam',
|
||||
'fr-CA': 'ca',
|
||||
'hi': 'in+bolnagri',
|
||||
'ky': 'kg',
|
||||
'nl-BE': 'be',
|
||||
'zu': None
|
||||
}
|
||||
|
||||
|
||||
def parse_single_key(value):
|
||||
def unescape(m):
|
||||
return chr(int(m.group(1), 16))
|
||||
value = ESCAPE_PATTERN.sub(unescape, value)
|
||||
return value
|
||||
|
||||
|
||||
def parse_rows(keymap):
|
||||
unsorted_rows = {}
|
||||
for _map in keymap.iter('map'):
|
||||
value = _map.get('to')
|
||||
key = [parse_single_key(value)]
|
||||
iso = _map.get('iso')
|
||||
if not ISO_PATTERN.match(iso):
|
||||
sys.stderr.write('invalid ISO key name: %s\n' % iso)
|
||||
continue
|
||||
if not iso[0] in unsorted_rows:
|
||||
unsorted_rows[iso[0]] = []
|
||||
unsorted_rows[iso[0]].append((int(iso[1:]), key))
|
||||
# add subkeys
|
||||
longPress = _map.get('longPress')
|
||||
if longPress:
|
||||
for value in longPress.split(' '):
|
||||
subkey = parse_single_key(value)
|
||||
key.append(subkey)
|
||||
|
||||
rows = []
|
||||
for k, v in sorted(list(unsorted_rows.items()),
|
||||
key=lambda x: x[0],
|
||||
reverse=True):
|
||||
row = []
|
||||
for key in sorted(v, key=lambda x: x):
|
||||
row.append(key[1])
|
||||
rows.append(row)
|
||||
|
||||
return rows
|
||||
|
||||
|
||||
def convert_xml(tree):
|
||||
root = {}
|
||||
for xml_keyboard in tree.iter("keyboard"):
|
||||
locale_full = xml_keyboard.get("locale")
|
||||
locale, sep, end = locale_full.partition("-t-")
|
||||
root["locale"] = locale
|
||||
for xml_name in tree.iter("name"):
|
||||
name = xml_name.get("value")
|
||||
root["name"] = name
|
||||
root["levels"] = []
|
||||
# parse levels
|
||||
for index, keymap in enumerate(tree.iter('keyMap')):
|
||||
# FIXME: heuristics here
|
||||
modifiers = keymap.get('modifiers')
|
||||
if not modifiers:
|
||||
mode = 'default'
|
||||
modifiers = ''
|
||||
elif 'shift' in modifiers.split(' '):
|
||||
mode = 'latched'
|
||||
modifiers = 'shift'
|
||||
else:
|
||||
mode = 'locked'
|
||||
level = {}
|
||||
level["level"] = modifiers
|
||||
level["mode"] = mode
|
||||
level["rows"] = parse_rows(keymap)
|
||||
root["levels"].append(level)
|
||||
return root
|
||||
|
||||
|
||||
def locale_to_xkb(locale, name):
|
||||
if locale in sorted(LOCALE_TO_XKB_OVERRIDES.keys()):
|
||||
xkb = LOCALE_TO_XKB_OVERRIDES[locale]
|
||||
logging.debug("override for %s → %s",
|
||||
locale, xkb)
|
||||
if xkb:
|
||||
return xkb
|
||||
else:
|
||||
raise KeyError("layout %s explicitely disabled in overrides"
|
||||
% locale)
|
||||
xkb_names = sorted(name_to_xkb.keys())
|
||||
if name in xkb_names:
|
||||
return name_to_xkb[name]
|
||||
else:
|
||||
logging.debug("name %s failed" % name)
|
||||
for sub_name in name.split(' '):
|
||||
if sub_name in xkb_names:
|
||||
xkb = name_to_xkb[sub_name]
|
||||
logging.debug("dumb mapping failed but match with locale word: "
|
||||
"%s (%s) → %s (%s)",
|
||||
locale, name, xkb, sub_name)
|
||||
return xkb
|
||||
else:
|
||||
logging.debug("sub_name failed")
|
||||
for xkb_name in xkb_names:
|
||||
for xkb_sub_name in xkb_name.split(' '):
|
||||
if xkb_sub_name.strip('()') == name:
|
||||
xkb = name_to_xkb[xkb_name]
|
||||
logging.debug("dumb mapping failed but match with xkb word: "
|
||||
"%s (%s) → %s (%s)",
|
||||
locale, name, xkb, xkb_name)
|
||||
return xkb
|
||||
raise KeyError("failed to find XKB mapping for %s" % locale)
|
||||
|
||||
|
||||
def convert_file(source_file, destination_path):
|
||||
logging.info("Parsing %s", source_file)
|
||||
|
||||
itree = xml.etree.ElementTree.ElementTree()
|
||||
itree.parse(source_file)
|
||||
|
||||
root = convert_xml(itree)
|
||||
|
||||
try:
|
||||
xkb_name = locale_to_xkb(root["locale"], root["name"])
|
||||
except KeyError as e:
|
||||
logging.warn(e)
|
||||
return False
|
||||
destination_file = os.path.join(destination_path, xkb_name + ".json")
|
||||
|
||||
with open(destination_file, 'w', encoding="utf-8") as dest_fd:
|
||||
json.dump(root, dest_fd, ensure_ascii=False, indent=2, sort_keys=True)
|
||||
|
||||
logging.debug("written %s", destination_file)
|
||||
|
||||
|
||||
def load_xkb_mappings():
|
||||
xkb = GnomeDesktop.XkbInfo()
|
||||
layouts = xkb.get_all_layouts()
|
||||
name_to_xkb = {}
|
||||
|
||||
for layout in layouts:
|
||||
name = xkb.get_layout_info(layout).display_name
|
||||
name_to_xkb[name] = layout
|
||||
|
||||
return name_to_xkb
|
||||
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "C")
|
||||
name_to_xkb = load_xkb_mappings()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if "DEBUG" in os.environ:
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("supply a CLDR keyboard file")
|
||||
sys.exit(1)
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("supply an output directory")
|
||||
sys.exit(1)
|
||||
|
||||
source = sys.argv[1]
|
||||
destination = sys.argv[2]
|
||||
if os.path.isfile(source):
|
||||
convert_file(source, destination)
|
||||
elif os.path.isdir(source):
|
||||
for path in glob.glob(source + "/*-t-k0-android.xml"):
|
||||
convert_file(path, destination)
|
@@ -9,9 +9,6 @@
|
||||
<method name="ShowOSD">
|
||||
<arg type="a{sv}" direction="in" name="params"/>
|
||||
</method>
|
||||
<method name="ShowMonitorLabels">
|
||||
<arg type="a{uv}" direction="in" name="params"/>
|
||||
</method>
|
||||
<method name="ShowMonitorLabels2">
|
||||
<arg type="a{sv}" direction="in" name="params"/>
|
||||
</method>
|
||||
@@ -34,6 +31,10 @@
|
||||
<arg type="u" direction="in" name="action"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<method name="UngrabAccelerators">
|
||||
<arg type="au" direction="in" name="action"/>
|
||||
<arg type="b" direction="out" name="success"/>
|
||||
</method>
|
||||
<signal name="AcceleratorActivated">
|
||||
<arg name="action" type="u"/>
|
||||
<arg name="parameters" type="a{sv}"/>
|
||||
|
@@ -6,6 +6,7 @@
|
||||
<file>be.json</file>
|
||||
<file>bg.json</file>
|
||||
<file>by.json</file>
|
||||
<file>ca.json</file>
|
||||
<file>cz.json</file>
|
||||
<file>de.json</file>
|
||||
<file>dk.json</file>
|
||||
|
599
data/osk-layouts/ca.json
Normal file
599
data/osk-layouts/ca.json
Normal file
@@ -0,0 +1,599 @@
|
||||
{
|
||||
"levels": [
|
||||
{
|
||||
"level": "",
|
||||
"mode": "default",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"q"
|
||||
],
|
||||
[
|
||||
"w"
|
||||
],
|
||||
[
|
||||
"e",
|
||||
"é",
|
||||
"è",
|
||||
"ê",
|
||||
"ë",
|
||||
"%",
|
||||
"ę",
|
||||
"ė",
|
||||
"ē"
|
||||
],
|
||||
[
|
||||
"r"
|
||||
],
|
||||
[
|
||||
"t"
|
||||
],
|
||||
[
|
||||
"y",
|
||||
"%",
|
||||
"ÿ"
|
||||
],
|
||||
[
|
||||
"u",
|
||||
"ù",
|
||||
"û",
|
||||
"%",
|
||||
"ü",
|
||||
"ú",
|
||||
"ū"
|
||||
],
|
||||
[
|
||||
"i",
|
||||
"î",
|
||||
"%",
|
||||
"ï",
|
||||
"ì",
|
||||
"í",
|
||||
"į",
|
||||
"ī"
|
||||
],
|
||||
[
|
||||
"o",
|
||||
"ô",
|
||||
"œ",
|
||||
"%",
|
||||
"ö",
|
||||
"ò",
|
||||
"ó",
|
||||
"õ",
|
||||
"ø",
|
||||
"ō",
|
||||
"º"
|
||||
],
|
||||
[
|
||||
"p"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"a",
|
||||
"à",
|
||||
"â",
|
||||
"%",
|
||||
"æ",
|
||||
"á",
|
||||
"ä",
|
||||
"ã",
|
||||
"å",
|
||||
"ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"s"
|
||||
],
|
||||
[
|
||||
"d"
|
||||
],
|
||||
[
|
||||
"f"
|
||||
],
|
||||
[
|
||||
"g"
|
||||
],
|
||||
[
|
||||
"h"
|
||||
],
|
||||
[
|
||||
"j"
|
||||
],
|
||||
[
|
||||
"k"
|
||||
],
|
||||
[
|
||||
"l"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"z"
|
||||
],
|
||||
[
|
||||
"x"
|
||||
],
|
||||
[
|
||||
"c",
|
||||
"ç",
|
||||
"ć",
|
||||
"č"
|
||||
],
|
||||
[
|
||||
"v"
|
||||
],
|
||||
[
|
||||
"b"
|
||||
],
|
||||
[
|
||||
"n"
|
||||
],
|
||||
[
|
||||
"m"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
".",
|
||||
"#",
|
||||
"!",
|
||||
",",
|
||||
"?",
|
||||
"-",
|
||||
":",
|
||||
"'",
|
||||
"@"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"level": "shift",
|
||||
"mode": "latched",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"Q"
|
||||
],
|
||||
[
|
||||
"W"
|
||||
],
|
||||
[
|
||||
"E",
|
||||
"É",
|
||||
"È",
|
||||
"Ê",
|
||||
"Ë",
|
||||
"%",
|
||||
"Ę",
|
||||
"Ė",
|
||||
"Ē"
|
||||
],
|
||||
[
|
||||
"R"
|
||||
],
|
||||
[
|
||||
"T"
|
||||
],
|
||||
[
|
||||
"Y",
|
||||
"%",
|
||||
"Ÿ"
|
||||
],
|
||||
[
|
||||
"U",
|
||||
"Ù",
|
||||
"Û",
|
||||
"%",
|
||||
"Ü",
|
||||
"Ú",
|
||||
"Ū"
|
||||
],
|
||||
[
|
||||
"I",
|
||||
"Î",
|
||||
"%",
|
||||
"Ï",
|
||||
"Ì",
|
||||
"Í",
|
||||
"Į",
|
||||
"Ī"
|
||||
],
|
||||
[
|
||||
"O",
|
||||
"Ô",
|
||||
"Œ",
|
||||
"%",
|
||||
"Ö",
|
||||
"Ò",
|
||||
"Ó",
|
||||
"Õ",
|
||||
"Ø",
|
||||
"Ō",
|
||||
"º"
|
||||
],
|
||||
[
|
||||
"P"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"A",
|
||||
"À",
|
||||
"Â",
|
||||
"%",
|
||||
"Æ",
|
||||
"Á",
|
||||
"Ä",
|
||||
"Ã",
|
||||
"Å",
|
||||
"Ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"S"
|
||||
],
|
||||
[
|
||||
"D"
|
||||
],
|
||||
[
|
||||
"F"
|
||||
],
|
||||
[
|
||||
"G"
|
||||
],
|
||||
[
|
||||
"H"
|
||||
],
|
||||
[
|
||||
"J"
|
||||
],
|
||||
[
|
||||
"K"
|
||||
],
|
||||
[
|
||||
"L"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"Z"
|
||||
],
|
||||
[
|
||||
"X"
|
||||
],
|
||||
[
|
||||
"C",
|
||||
"Ç",
|
||||
"Ć",
|
||||
"Č"
|
||||
],
|
||||
[
|
||||
"V"
|
||||
],
|
||||
[
|
||||
"B"
|
||||
],
|
||||
[
|
||||
"N"
|
||||
],
|
||||
[
|
||||
"M"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
".",
|
||||
"#",
|
||||
"!",
|
||||
",",
|
||||
"?",
|
||||
"-",
|
||||
":",
|
||||
"'",
|
||||
"@"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"level": "opt",
|
||||
"mode": "locked",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"1",
|
||||
"¹",
|
||||
"½",
|
||||
"⅓",
|
||||
"¼",
|
||||
"⅛"
|
||||
],
|
||||
[
|
||||
"2",
|
||||
"²",
|
||||
"⅔"
|
||||
],
|
||||
[
|
||||
"3",
|
||||
"³",
|
||||
"¾",
|
||||
"⅜"
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"⁴"
|
||||
],
|
||||
[
|
||||
"5",
|
||||
"⅝"
|
||||
],
|
||||
[
|
||||
"6"
|
||||
],
|
||||
[
|
||||
"7",
|
||||
"⅞"
|
||||
],
|
||||
[
|
||||
"8"
|
||||
],
|
||||
[
|
||||
"9"
|
||||
],
|
||||
[
|
||||
"0",
|
||||
"ⁿ",
|
||||
"∅"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"@"
|
||||
],
|
||||
[
|
||||
"#"
|
||||
],
|
||||
[
|
||||
"$",
|
||||
"¢",
|
||||
"£",
|
||||
"€",
|
||||
"¥",
|
||||
"₱"
|
||||
],
|
||||
[
|
||||
"%",
|
||||
"‰"
|
||||
],
|
||||
[
|
||||
"&"
|
||||
],
|
||||
[
|
||||
"-",
|
||||
"_",
|
||||
"–",
|
||||
"—",
|
||||
"·"
|
||||
],
|
||||
[
|
||||
"+",
|
||||
"±"
|
||||
],
|
||||
[
|
||||
"(",
|
||||
"<",
|
||||
"{",
|
||||
"["
|
||||
],
|
||||
[
|
||||
")",
|
||||
">",
|
||||
"}",
|
||||
"]"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"*",
|
||||
"†",
|
||||
"‡",
|
||||
"★"
|
||||
],
|
||||
[
|
||||
"\"",
|
||||
"“",
|
||||
"”",
|
||||
"«",
|
||||
"»"
|
||||
],
|
||||
[
|
||||
"'",
|
||||
"‘",
|
||||
"’",
|
||||
"‹",
|
||||
"›"
|
||||
],
|
||||
[
|
||||
":"
|
||||
],
|
||||
[
|
||||
";"
|
||||
],
|
||||
[
|
||||
"!",
|
||||
"¡"
|
||||
],
|
||||
[
|
||||
"?",
|
||||
"¿"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"_"
|
||||
],
|
||||
[
|
||||
"/"
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
".",
|
||||
"…"
|
||||
]
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"level": "opt+shift",
|
||||
"mode": "locked",
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"~"
|
||||
],
|
||||
[
|
||||
"`"
|
||||
],
|
||||
[
|
||||
"|"
|
||||
],
|
||||
[
|
||||
"•",
|
||||
"♪",
|
||||
"♥",
|
||||
"♠",
|
||||
"♦",
|
||||
"♣"
|
||||
],
|
||||
[
|
||||
"√"
|
||||
],
|
||||
[
|
||||
"Π",
|
||||
"π"
|
||||
],
|
||||
[
|
||||
"÷"
|
||||
],
|
||||
[
|
||||
"×"
|
||||
],
|
||||
[
|
||||
"¶",
|
||||
"§"
|
||||
],
|
||||
[
|
||||
"∆"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"£"
|
||||
],
|
||||
[
|
||||
"¢"
|
||||
],
|
||||
[
|
||||
"€"
|
||||
],
|
||||
[
|
||||
"¥"
|
||||
],
|
||||
[
|
||||
"^",
|
||||
"↑",
|
||||
"↓",
|
||||
"←",
|
||||
"→"
|
||||
],
|
||||
[
|
||||
"°",
|
||||
"′",
|
||||
"″"
|
||||
],
|
||||
[
|
||||
"=",
|
||||
"≠",
|
||||
"≈",
|
||||
"∞"
|
||||
],
|
||||
[
|
||||
"{"
|
||||
],
|
||||
[
|
||||
"}"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"\\"
|
||||
],
|
||||
[
|
||||
"©"
|
||||
],
|
||||
[
|
||||
"®"
|
||||
],
|
||||
[
|
||||
"™"
|
||||
],
|
||||
[
|
||||
"℅"
|
||||
],
|
||||
[
|
||||
"["
|
||||
],
|
||||
[
|
||||
"]"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"<",
|
||||
"‹",
|
||||
"≤",
|
||||
"«"
|
||||
],
|
||||
[
|
||||
">",
|
||||
"›",
|
||||
"≥",
|
||||
"»"
|
||||
],
|
||||
[
|
||||
" "
|
||||
],
|
||||
[
|
||||
","
|
||||
],
|
||||
[
|
||||
".",
|
||||
"…"
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
],
|
||||
"locale": "fr-CA",
|
||||
"name": "French Canada"
|
||||
}
|
@@ -6,10 +6,20 @@
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"q"
|
||||
"a",
|
||||
"à",
|
||||
"â",
|
||||
"%",
|
||||
"æ",
|
||||
"á",
|
||||
"ä",
|
||||
"ã",
|
||||
"å",
|
||||
"ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"w"
|
||||
"z"
|
||||
],
|
||||
[
|
||||
"e",
|
||||
@@ -71,17 +81,7 @@
|
||||
],
|
||||
[
|
||||
[
|
||||
"a",
|
||||
"à",
|
||||
"â",
|
||||
"%",
|
||||
"æ",
|
||||
"á",
|
||||
"ä",
|
||||
"ã",
|
||||
"å",
|
||||
"ā",
|
||||
"ª"
|
||||
"q"
|
||||
],
|
||||
[
|
||||
"s"
|
||||
@@ -106,11 +106,14 @@
|
||||
],
|
||||
[
|
||||
"l"
|
||||
],
|
||||
[
|
||||
"m"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"z"
|
||||
"w"
|
||||
],
|
||||
[
|
||||
"x"
|
||||
@@ -131,7 +134,11 @@
|
||||
"n"
|
||||
],
|
||||
[
|
||||
"m"
|
||||
"'",
|
||||
"‘",
|
||||
"’",
|
||||
"‹",
|
||||
"›"
|
||||
]
|
||||
],
|
||||
[
|
||||
@@ -161,10 +168,20 @@
|
||||
"rows": [
|
||||
[
|
||||
[
|
||||
"Q"
|
||||
"A",
|
||||
"À",
|
||||
"Â",
|
||||
"%",
|
||||
"Æ",
|
||||
"Á",
|
||||
"Ä",
|
||||
"Ã",
|
||||
"Å",
|
||||
"Ā",
|
||||
"ª"
|
||||
],
|
||||
[
|
||||
"W"
|
||||
"Z"
|
||||
],
|
||||
[
|
||||
"E",
|
||||
@@ -226,17 +243,7 @@
|
||||
],
|
||||
[
|
||||
[
|
||||
"A",
|
||||
"À",
|
||||
"Â",
|
||||
"%",
|
||||
"Æ",
|
||||
"Á",
|
||||
"Ä",
|
||||
"Ã",
|
||||
"Å",
|
||||
"Ā",
|
||||
"ª"
|
||||
"Q"
|
||||
],
|
||||
[
|
||||
"S"
|
||||
@@ -261,11 +268,14 @@
|
||||
],
|
||||
[
|
||||
"L"
|
||||
],
|
||||
[
|
||||
"M"
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
"Z"
|
||||
"W"
|
||||
],
|
||||
[
|
||||
"X"
|
||||
@@ -286,7 +296,11 @@
|
||||
"N"
|
||||
],
|
||||
[
|
||||
"M"
|
||||
"'",
|
||||
"‘",
|
||||
"’",
|
||||
"‹",
|
||||
"›"
|
||||
]
|
||||
],
|
||||
[
|
||||
@@ -369,10 +383,10 @@
|
||||
"#"
|
||||
],
|
||||
[
|
||||
"$",
|
||||
"€",
|
||||
"¢",
|
||||
"£",
|
||||
"€",
|
||||
"$",
|
||||
"¥",
|
||||
"₱"
|
||||
],
|
||||
@@ -511,13 +525,14 @@
|
||||
"£"
|
||||
],
|
||||
[
|
||||
"¥"
|
||||
],
|
||||
[
|
||||
"$",
|
||||
"¢"
|
||||
],
|
||||
[
|
||||
"€"
|
||||
],
|
||||
[
|
||||
"¥"
|
||||
"¢"
|
||||
],
|
||||
[
|
||||
"^",
|
||||
@@ -594,6 +609,6 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"locale": "fr-CA",
|
||||
"name": "French Canada"
|
||||
"locale": "fr",
|
||||
"name": "French"
|
||||
}
|
@@ -16,12 +16,12 @@ $link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), li
|
||||
$top_hilight: $borders_edge;
|
||||
|
||||
$warning_color: #f57900;
|
||||
$error_color: #cc0000;
|
||||
$error_color: #ff8080;
|
||||
$success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
|
||||
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
|
||||
|
||||
$osd_fg_color: #eeeeec;
|
||||
$osd_bg_color: #2e3436;
|
||||
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 15%),0.3);
|
||||
$osd_borders_color: transparentize(black, 0.3);
|
||||
$osd_outer_borders_color: transparentize(white, 0.9);
|
||||
|
||||
|
@@ -29,7 +29,7 @@ $panel-corner-radius: 6px;
|
||||
/* GLOBALS */
|
||||
$font-size: 11;
|
||||
$font-family: Cantarell, Sans-Serif;
|
||||
$_bubble_bg_color: opacify($osd_bg_color,0.25);
|
||||
$_bubble_bg_color: $osd_bg_color;
|
||||
$_bubble_fg_color: $osd_fg_color;
|
||||
$_bubble_borders_color: transparentize($osd_fg_color,0.8);
|
||||
|
||||
@@ -184,7 +184,7 @@ StScrollBar {
|
||||
.modal-dialog {
|
||||
border-radius: 9px;
|
||||
color: $osd_fg_color;
|
||||
background-color: transparentize(darken($osd_bg_color,10%),0.05);
|
||||
background-color: $osd_bg_color;
|
||||
border: 1px solid $_bubble_borders_color;
|
||||
.modal-dialog-content-box {
|
||||
padding: 24px;
|
||||
@@ -267,8 +267,7 @@ StScrollBar {
|
||||
}
|
||||
|
||||
.end-session-dialog-logout-icon {
|
||||
//border: 2px solid #8b8b8b;
|
||||
border-radius: 5px;
|
||||
border-radius: 99px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
background-size: contain;
|
||||
@@ -393,7 +392,7 @@ StScrollBar {
|
||||
|
||||
.prompt-dialog-error-label {
|
||||
font-size: 10pt;
|
||||
color: $error_color;
|
||||
color: $warning_color;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
@@ -428,7 +427,7 @@ StScrollBar {
|
||||
}
|
||||
|
||||
.polkit-dialog-user-icon {
|
||||
border-radius: 5px;
|
||||
border-radius: 99px;
|
||||
background-size: contain;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
@@ -508,6 +507,7 @@ StScrollBar {
|
||||
|
||||
.popup-menu-arrow { } //defined globally in the TOP BAR
|
||||
.popup-sub-menu {
|
||||
padding-bottom: 1px;
|
||||
background-color: darken($bg_color,2%);
|
||||
box-shadow: inset 0 -1px 0px lighten($borders_color,5%);
|
||||
}
|
||||
@@ -1031,6 +1031,11 @@ StScrollBar {
|
||||
-st-icon-style: symbolic;
|
||||
}
|
||||
|
||||
.message-icon-bin > .fallback-window-icon {
|
||||
width: 1.09em;
|
||||
height: 1.09em;
|
||||
}
|
||||
|
||||
.message-secondary-bin {
|
||||
padding: 0 0.82em;;
|
||||
}
|
||||
@@ -1137,8 +1142,14 @@ StScrollBar {
|
||||
|
||||
.ripple-box:rtl { border-radius: 0 0 0 52px; } // just a simple change to the border radius position
|
||||
|
||||
// Rubberband for select-area screenshots
|
||||
.select-area-rubberband {
|
||||
background-color: transparentize($selected_bg_color,0.7);
|
||||
border: 1px solid $selected_bg_color;
|
||||
}
|
||||
|
||||
// not really top bar only
|
||||
.popup-menu-arrow { width: 16px; height: 16px; }
|
||||
.popup-menu-arrow { icon-size: 1.09em; }
|
||||
.popup-menu-icon { icon-size: 1.09em; }
|
||||
|
||||
//close buttons
|
||||
@@ -1284,6 +1295,8 @@ StScrollBar {
|
||||
|
||||
.search-section-separator { height: 2px; background-color: rgba(255, 255, 255, 0.2); }
|
||||
|
||||
.search-section:last-child .search-section-separator { background-color: transparent; }
|
||||
|
||||
.list-search-result-content { spacing: 30px; }
|
||||
.list-search-result-title { color: darken($osd_fg_color,5%); spacing: 12px; }
|
||||
.list-search-result-description { color: transparentize(darken($osd_fg_color,15%), 0.5); }
|
||||
@@ -1446,13 +1459,13 @@ StScrollBar {
|
||||
height: 12px;
|
||||
background-color: transparent;
|
||||
border: 2px solid rgba(255, 255, 255, 0.4);
|
||||
border-radius:12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
&:hover .page-indicator-icon { border-color: white; }
|
||||
&:active .page-indicator-icon { border: none; margin: 2px; background-color:#fff; }
|
||||
&:active .page-indicator-icon { border: none; margin: 2px; background-color: white; }
|
||||
&:checked .page-indicator-icon,
|
||||
&:checked:active { background-color: #fff;}
|
||||
&:checked:active .page-indicator-icon { background-color: white;}
|
||||
}
|
||||
|
||||
.no-frequent-applications-label { @extend %status_text; }
|
||||
@@ -1754,13 +1767,11 @@ StScrollBar {
|
||||
|
||||
/* Auth Dialogs & Screen Shield */
|
||||
|
||||
.framed-user-icon {
|
||||
.user-icon {
|
||||
background-size: contain;
|
||||
border: 2px solid $osd_fg_color;
|
||||
color: $osd_fg_color;
|
||||
border-radius: 3px;
|
||||
border-radius: 99px;
|
||||
&:hover {
|
||||
border-color: lighten($osd_fg_color,30%);
|
||||
color: lighten($osd_fg_color,30%);
|
||||
}
|
||||
}
|
||||
|
@@ -111,7 +111,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
|
||||
@mixin button($t, $c:opacify(lighten($osd_bg_color, 5%),1.0), $tc:$fg_color, $edge: $borders_edge) {
|
||||
//
|
||||
// Button drawing function
|
||||
//
|
||||
@@ -136,8 +136,7 @@
|
||||
//
|
||||
// normal button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
|
||||
$osd_bg_color);
|
||||
$_bg: $c;
|
||||
|
||||
color: $osd_fg_color;
|
||||
background-color: $_bg;
|
||||
@@ -150,8 +149,7 @@
|
||||
//
|
||||
// focused button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
|
||||
lighten($osd_bg_color,3%));
|
||||
$_bg: lighten($c,3%);
|
||||
|
||||
color: $osd_fg_color;
|
||||
text-shadow: 0 1px black;
|
||||
@@ -163,8 +161,7 @@
|
||||
//
|
||||
// active osd button
|
||||
//
|
||||
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
|
||||
lighten($osd_bg_color,3%));
|
||||
$_bg: lighten($c,3%);
|
||||
|
||||
color: white;
|
||||
border-color: $osd_borders_color;
|
||||
|
@@ -40,6 +40,7 @@ do
|
||||
done
|
||||
|
||||
cat >>$TMP_GRESOURCE_FILE <<EOF
|
||||
<file>emoji.json</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
EOF
|
||||
|
@@ -551,9 +551,9 @@ class ExtensionRow extends Gtk.ListBoxRow {
|
||||
|
||||
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
|
||||
no_show_all: true });
|
||||
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
|
||||
icon_size: Gtk.IconSize.BUTTON,
|
||||
visible: true }));
|
||||
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
|
||||
icon_size: Gtk.IconSize.BUTTON,
|
||||
visible: true }));
|
||||
button.get_style_context().add_class('circular');
|
||||
hbox.add(button);
|
||||
|
||||
|
@@ -481,6 +481,9 @@ var LoginDialog = GObject.registerClass({
|
||||
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
|
||||
x_align: Clutter.ActorAlign.CENTER,
|
||||
y_align: Clutter.ActorAlign.END });
|
||||
this._logoBin.connect('resource-scale-changed', () => {
|
||||
this._updateLogoTexture(this._textureCache, this._logoFile);
|
||||
});
|
||||
this.add_child(this._logoBin);
|
||||
this._updateLogo();
|
||||
|
||||
@@ -778,11 +781,12 @@ var LoginDialog = GObject.registerClass({
|
||||
return;
|
||||
|
||||
this._logoBin.destroy_all_children();
|
||||
if (this._logoFile) {
|
||||
if (this._logoFile && this._logoBin.resource_scale > 0) {
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
|
||||
-1, _LOGO_ICON_HEIGHT,
|
||||
scaleFactor));
|
||||
scaleFactor,
|
||||
this._logoBin.resource_scale));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,10 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
const { Clutter, GObject, IBus } = imports.gi;
|
||||
const { Clutter, GLib, GObject, IBus } = imports.gi;
|
||||
|
||||
const Keyboard = imports.ui.status.keyboard;
|
||||
|
||||
var HIDE_PANEL_TIME = 50;
|
||||
|
||||
var InputMethod = GObject.registerClass(
|
||||
class InputMethod extends Clutter.InputMethod {
|
||||
_init() {
|
||||
@@ -13,6 +15,7 @@ class InputMethod extends Clutter.InputMethod {
|
||||
this._preeditStr = '';
|
||||
this._preeditPos = 0;
|
||||
this._preeditVisible = false;
|
||||
this._hidePanelId = 0;
|
||||
this._ibus = IBus.Bus.new_async();
|
||||
this._ibus.connect('connected', this._onConnected.bind(this));
|
||||
this._ibus.connect('disconnected', this._clear.bind(this));
|
||||
@@ -136,6 +139,11 @@ class InputMethod extends Clutter.InputMethod {
|
||||
this._updateCapabilities();
|
||||
this._emitRequestSurrounding();
|
||||
}
|
||||
|
||||
if (this._hidePanelId) {
|
||||
GLib.source_remove(this._hidePanelId);
|
||||
this._hidePanelId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vfunc_focus_out() {
|
||||
@@ -150,6 +158,12 @@ class InputMethod extends Clutter.InputMethod {
|
||||
this.set_preedit_text(null, 0);
|
||||
this._preeditStr = null;
|
||||
}
|
||||
|
||||
this._hidePanelId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, HIDE_PANEL_TIME, () => {
|
||||
this.set_input_panel_state(Clutter.InputPanelState.OFF);
|
||||
this._hidePanelId = 0;
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_reset() {
|
||||
|
@@ -30,6 +30,14 @@ var WeatherClient = class {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._permStore.g_name_owner == null) {
|
||||
// Failed to auto-start, likely because xdg-desktop-portal
|
||||
// isn't installed; don't restrict access to location service
|
||||
this._weatherAuthorized = true;
|
||||
this._updateAutoLocation();
|
||||
return;
|
||||
}
|
||||
|
||||
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
|
||||
if (error)
|
||||
log('Error looking up permission: ' + error.message);
|
||||
|
@@ -10,7 +10,7 @@ const Scripting = imports.ui.scripting;
|
||||
// someone should be able to get an idea of how well the shell is performing
|
||||
// on a particular system.
|
||||
|
||||
let METRICS = {
|
||||
var METRICS = {
|
||||
overviewLatencyFirst:
|
||||
{ description: "Time to first frame after triggering overview, first time",
|
||||
units: "us" },
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { Clutter, Gio, Gtk, Shell } = imports.gi;
|
||||
const { Clutter, Gio, Shell } = imports.gi;
|
||||
const Main = imports.ui.main;
|
||||
const Scripting = imports.ui.scripting;
|
||||
|
||||
let METRICS = {
|
||||
var METRICS = {
|
||||
timeToDesktop:
|
||||
{ description: "Time from starting graphical.target to desktop showing",
|
||||
units: "us" },
|
||||
@@ -104,7 +104,10 @@ function *run() {
|
||||
yield Scripting.waitLeisure();
|
||||
Scripting.scriptEvent('desktopShown');
|
||||
|
||||
Gtk.Settings.get_default().gtk_enable_animations = false;
|
||||
let interfaceSettings = new Gio.Settings({
|
||||
schema_id: 'org.gnome.desktop.interface'
|
||||
});
|
||||
interfaceSettings.set_boolean('enable-animations', false);
|
||||
|
||||
Scripting.scriptEvent('overviewShowStart');
|
||||
Main.overview.show();
|
||||
@@ -200,7 +203,7 @@ function *run() {
|
||||
|
||||
yield Scripting.sleep(1000);
|
||||
|
||||
Gtk.Settings.get_default().gtk_enable_animations = true;
|
||||
interfaceSettings.set_boolean('enable-animations', true);
|
||||
}
|
||||
|
||||
let overviewShowStart;
|
||||
|
@@ -619,9 +619,8 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
|
||||
var WindowCyclerPopup = GObject.registerClass(
|
||||
class WindowCyclerPopup extends CyclerPopup {
|
||||
_init() {
|
||||
super._init();
|
||||
|
||||
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
|
||||
super._init();
|
||||
}
|
||||
|
||||
_getWindows() {
|
||||
|
@@ -12,7 +12,16 @@ var SPINNER_ANIMATION_DELAY = 1.0;
|
||||
var Animation = class {
|
||||
constructor(file, width, height, speed) {
|
||||
this.actor = new St.Bin();
|
||||
this.actor.set_size(width, height);
|
||||
this.actor.connect('destroy', this._onDestroy.bind(this));
|
||||
this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
|
||||
this.actor.connect('resource-scale-changed',
|
||||
this._loadFile.bind(this, file, width, height));
|
||||
|
||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||
this._scaleChangedId = themeContext.connect('notify::scale-factor',
|
||||
this._loadFile.bind(this, file, width, height));
|
||||
|
||||
this._speed = speed;
|
||||
|
||||
this._isLoaded = false;
|
||||
@@ -20,10 +29,7 @@ var Animation = class {
|
||||
this._timeoutId = 0;
|
||||
this._frame = 0;
|
||||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor,
|
||||
this._animationsLoaded.bind(this));
|
||||
this.actor.set_child(this._animations);
|
||||
this._loadFile(file, width, height);
|
||||
}
|
||||
|
||||
play() {
|
||||
@@ -47,6 +53,23 @@ var Animation = class {
|
||||
this._isPlaying = false;
|
||||
}
|
||||
|
||||
_loadFile(file, width, height) {
|
||||
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
|
||||
|
||||
this._isLoaded = false;
|
||||
this.actor.destroy_all_children();
|
||||
|
||||
if (!validResourceScale)
|
||||
return;
|
||||
|
||||
let texture_cache = St.TextureCache.get_default();
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this._animations = texture_cache.load_sliced_image(file, width, height,
|
||||
scaleFactor, resourceScale,
|
||||
this._animationsLoaded.bind(this));
|
||||
this.actor.set_child(this._animations);
|
||||
}
|
||||
|
||||
_showFrame(frame) {
|
||||
let oldFrameActor = this._animations.get_child_at_index(this._frame);
|
||||
if (oldFrameActor)
|
||||
@@ -64,15 +87,32 @@ var Animation = class {
|
||||
return GLib.SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
_syncAnimationSize() {
|
||||
if (!this._isLoaded)
|
||||
return;
|
||||
|
||||
let [width, height] = this.actor.get_size();
|
||||
|
||||
for (let i = 0; i < this._animations.get_n_children(); ++i)
|
||||
this._animations.get_child_at_index(i).set_size(width, height);
|
||||
}
|
||||
|
||||
_animationsLoaded() {
|
||||
this._isLoaded = this._animations.get_n_children() > 0;
|
||||
|
||||
this._syncAnimationSize();
|
||||
|
||||
if (this._isPlaying)
|
||||
this.play();
|
||||
}
|
||||
|
||||
_onDestroy() {
|
||||
this.stop();
|
||||
|
||||
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
||||
if (this._scaleChangedId)
|
||||
themeContext.disconnect(this._scaleChangedId);
|
||||
this._scaleChangedId = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -14,39 +14,47 @@ const RENAMED_DESKTOP_IDS = {
|
||||
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
|
||||
'evolution.desktop': 'org.gnome.Evolution.desktop',
|
||||
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
|
||||
'five-or-more.desktop': 'org.gnome.five-or-more.desktop',
|
||||
'four-in-a-row.desktop': 'org.gnome.Four-in-a-row.desktop',
|
||||
'gcalctool.desktop': 'org.gnome.Calculator.desktop',
|
||||
'geary.desktop': 'org.gnome.Geary.desktop',
|
||||
'gedit.desktop': 'org.gnome.gedit.desktop',
|
||||
'glchess.desktop': 'gnome-chess.desktop',
|
||||
'glines.desktop': 'five-or-more.desktop',
|
||||
'gnect.desktop': 'four-in-a-row.desktop',
|
||||
'glchess.desktop': 'org.gnome.Chess.desktop',
|
||||
'glines.desktop': 'org.gnome.five-or-more.desktop',
|
||||
'gnect.desktop': 'org.gnome.Four-in-a-row.desktop',
|
||||
'gnibbles.desktop': 'org.gnome.Nibbles.desktop',
|
||||
'gnobots2.desktop': 'gnome-robots.desktop',
|
||||
'gnobots2.desktop': 'org.gnome.Robots.desktop',
|
||||
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
|
||||
'gnome-calculator.desktop': 'org.gnome.Calculator.desktop',
|
||||
'gnome-chess.desktop': 'org.gnome.Chess.desktop',
|
||||
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
|
||||
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
|
||||
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
|
||||
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
|
||||
'gnome-klotski.desktop': 'org.gnome.Klotski.desktop',
|
||||
'gnome-nibbles.desktop': 'org.gnome.Nibbles.desktop',
|
||||
'gnome-mahjongg.desktop': 'org.gnome.Mahjongg.desktop',
|
||||
'gnome-mines.desktop': 'org.gnome.Mines.desktop',
|
||||
'gnome-music.desktop': 'org.gnome.Music.desktop',
|
||||
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
|
||||
'gnome-robots.desktop': 'org.gnome.Robots.desktop',
|
||||
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
|
||||
'gnome-software.desktop': 'org.gnome.Software.desktop',
|
||||
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
|
||||
'gnome-tetravex.desktop': 'org.gnome.Tetravex.desktop',
|
||||
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
|
||||
'gnome-weather.desktop': 'org.gnome.Weather.desktop',
|
||||
'gnomine.desktop': 'gnome-mines.desktop',
|
||||
'gnotravex.desktop': 'gnome-tetravex.desktop',
|
||||
'gnotski.desktop': 'gnome-klotski.desktop',
|
||||
'gtali.desktop': 'tali.desktop',
|
||||
'gnomine.desktop': 'org.gnome.Mines.desktop',
|
||||
'gnotravex.desktop': 'org.gnome.Tetravex.desktop',
|
||||
'gnotski.desktop': 'org.gnome.Klotski.desktop',
|
||||
'gtali.desktop': 'org.gnome.Tali.desktop',
|
||||
'iagno.desktop': 'org.gnome.Reversi.desktop',
|
||||
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
|
||||
'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop',
|
||||
'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop',
|
||||
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
|
||||
'polari.desktop': 'org.gnome.Polari.desktop',
|
||||
'tali.desktop': 'org.gnome.Tali.desktop',
|
||||
'totem.desktop': 'org.gnome.Totem.desktop',
|
||||
'evince.desktop': 'org.gnome.Evince.desktop',
|
||||
};
|
||||
|
@@ -746,10 +746,8 @@ var BackgroundManager = class BackgroundManager {
|
||||
|
||||
this._container.add_child(backgroundActor);
|
||||
|
||||
let monitor = this._layoutManager.monitors[this._monitorIndex];
|
||||
|
||||
backgroundActor.set_size(monitor.width, monitor.height);
|
||||
if (this._controlPosition) {
|
||||
let monitor = this._layoutManager.monitors[this._monitorIndex];
|
||||
backgroundActor.set_position(monitor.x, monitor.y);
|
||||
backgroundActor.lower_bottom();
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ var POPUP_ANIMATION_TIME = 0.15;
|
||||
* placed. The arrow position may be controlled via
|
||||
* setArrowOrigin(). The arrow side might be temporarily flipped
|
||||
* depending on the box size and source position to keep the box
|
||||
* totally inside the monitor if possible.
|
||||
* totally inside the monitor workarea if possible.
|
||||
*
|
||||
*/
|
||||
var BoxPointer = GObject.registerClass({
|
||||
@@ -47,10 +47,6 @@ var BoxPointer = GObject.registerClass({
|
||||
this._border.connect('repaint', this._drawBorder.bind(this));
|
||||
this.add_actor(this._border);
|
||||
this.bin.raise(this._border);
|
||||
this._xOffset = 0;
|
||||
this._yOffset = 0;
|
||||
this._xPosition = 0;
|
||||
this._yPosition = 0;
|
||||
this._sourceAlignment = 0.5;
|
||||
this._capturedEventId = 0;
|
||||
this._muteInput();
|
||||
@@ -118,23 +114,23 @@ var BoxPointer = GObject.registerClass({
|
||||
if (animate & PopupAnimation.SLIDE) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
this.yOffset = -rise;
|
||||
this.translation_y = -rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
this.yOffset = rise;
|
||||
this.translation_y = rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
this.xOffset = -rise;
|
||||
this.translation_x = -rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
this.xOffset = rise;
|
||||
this.translation_x = rise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Tweener.addTween(this, { opacity: 255,
|
||||
xOffset: 0,
|
||||
yOffset: 0,
|
||||
translation_x: 0,
|
||||
translation_y: 0,
|
||||
transition: 'linear',
|
||||
onComplete: () => {
|
||||
this._unmuteInput();
|
||||
@@ -148,8 +144,8 @@ var BoxPointer = GObject.registerClass({
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
let xOffset = 0;
|
||||
let yOffset = 0;
|
||||
let translationX = 0;
|
||||
let translationY = 0;
|
||||
let themeNode = this.get_theme_node();
|
||||
let rise = themeNode.get_length('-arrow-rise');
|
||||
let fade = (animate & PopupAnimation.FADE);
|
||||
@@ -158,16 +154,16 @@ var BoxPointer = GObject.registerClass({
|
||||
if (animate & PopupAnimation.SLIDE) {
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
yOffset = rise;
|
||||
translationY = rise;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
yOffset = -rise;
|
||||
translationY = -rise;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
xOffset = rise;
|
||||
translationX = rise;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
xOffset = -rise;
|
||||
translationX = -rise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -176,15 +172,15 @@ var BoxPointer = GObject.registerClass({
|
||||
|
||||
Tweener.removeTweens(this);
|
||||
Tweener.addTween(this, { opacity: fade ? 0 : 255,
|
||||
xOffset: xOffset,
|
||||
yOffset: yOffset,
|
||||
translation_x: translationX,
|
||||
translation_y: translationY,
|
||||
transition: 'linear',
|
||||
time: animationTime,
|
||||
onComplete: () => {
|
||||
this.hide();
|
||||
this.opacity = 0;
|
||||
this.xOffset = 0;
|
||||
this.yOffset = 0;
|
||||
this.translation_x = 0;
|
||||
this.translation_y = 0;
|
||||
if (onComplete)
|
||||
onComplete();
|
||||
}
|
||||
@@ -477,11 +473,15 @@ var BoxPointer = GObject.registerClass({
|
||||
_reposition() {
|
||||
let sourceActor = this._sourceActor;
|
||||
let alignment = this._arrowAlignment;
|
||||
let monitorIndex = Main.layoutManager.findIndexForActor(sourceActor);
|
||||
|
||||
this._sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
||||
this._workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
|
||||
|
||||
// Position correctly relative to the sourceActor
|
||||
let sourceNode = sourceActor.get_theme_node();
|
||||
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
|
||||
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
|
||||
let sourceAllocation = this._sourceAllocation;
|
||||
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
|
||||
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
|
||||
let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
|
||||
@@ -489,7 +489,7 @@ var BoxPointer = GObject.registerClass({
|
||||
// We also want to keep it onscreen, and separated from the
|
||||
// edge by the same distance as the main part of the box is
|
||||
// separated from its sourceActor
|
||||
let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
|
||||
let workarea = this._workArea;
|
||||
let themeNode = this.get_theme_node();
|
||||
let borderWidth = themeNode.get_length('-arrow-border-width');
|
||||
let arrowBase = themeNode.get_length('-arrow-base');
|
||||
@@ -539,8 +539,8 @@ var BoxPointer = GObject.registerClass({
|
||||
case St.Side.BOTTOM:
|
||||
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
|
||||
|
||||
resX = Math.max(resX, monitor.x + padding);
|
||||
resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
|
||||
resX = Math.max(resX, workarea.x + padding);
|
||||
resX = Math.min(resX, workarea.x + workarea.width - (padding + natWidth));
|
||||
|
||||
arrowOrigin = sourceCenterX - resX;
|
||||
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
|
||||
@@ -558,8 +558,8 @@ var BoxPointer = GObject.registerClass({
|
||||
case St.Side.RIGHT:
|
||||
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
|
||||
|
||||
resY = Math.max(resY, monitor.y + padding);
|
||||
resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
|
||||
resY = Math.max(resY, workarea.y + padding);
|
||||
resY = Math.min(resY, workarea.y + workarea.height - (padding + natHeight));
|
||||
|
||||
arrowOrigin = sourceCenterY - resY;
|
||||
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
|
||||
@@ -583,9 +583,9 @@ var BoxPointer = GObject.registerClass({
|
||||
parent = parent.get_parent();
|
||||
}
|
||||
|
||||
this._xPosition = Math.floor(x);
|
||||
this._yPosition = Math.floor(y);
|
||||
this._shiftActor();
|
||||
// Actually set the position
|
||||
this.x = Math.floor(x);
|
||||
this.y = Math.floor(y);
|
||||
}
|
||||
|
||||
// @origin: Coordinate specifying middle of the arrow, along
|
||||
@@ -608,44 +608,30 @@ var BoxPointer = GObject.registerClass({
|
||||
}
|
||||
}
|
||||
|
||||
_shiftActor() {
|
||||
// Since the position of the BoxPointer depends on the allocated size
|
||||
// of the BoxPointer and the position of the source actor, trying
|
||||
// to position the BoxPointer via the x/y properties will result in
|
||||
// allocation loops and warnings. Instead we do the positioning via
|
||||
// the anchor point, which is independent of allocation, and leave
|
||||
// x == y == 0.
|
||||
this.set_anchor_point(-(this._xPosition + this._xOffset),
|
||||
-(this._yPosition + this._yOffset));
|
||||
}
|
||||
|
||||
_calculateArrowSide(arrowSide) {
|
||||
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
|
||||
let sourceAllocation = this._sourceAllocation;
|
||||
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
|
||||
let monitorActor = this.sourceActor;
|
||||
if (!monitorActor)
|
||||
monitorActor = this;
|
||||
let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
|
||||
let workarea = this._workArea;
|
||||
|
||||
switch (arrowSide) {
|
||||
case St.Side.TOP:
|
||||
if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
|
||||
boxHeight < sourceAllocation.y1 - monitor.y)
|
||||
if (sourceAllocation.y2 + boxHeight > workarea.y + workarea.height &&
|
||||
boxHeight < sourceAllocation.y1 - workarea.y)
|
||||
return St.Side.BOTTOM;
|
||||
break;
|
||||
case St.Side.BOTTOM:
|
||||
if (sourceAllocation.y1 - boxHeight < monitor.y &&
|
||||
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
|
||||
if (sourceAllocation.y1 - boxHeight < workarea.y &&
|
||||
boxHeight < workarea.y + workarea.height - sourceAllocation.y2)
|
||||
return St.Side.TOP;
|
||||
break;
|
||||
case St.Side.LEFT:
|
||||
if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width &&
|
||||
boxWidth < sourceAllocation.x1 - monitor.x)
|
||||
if (sourceAllocation.x2 + boxWidth > workarea.x + workarea.width &&
|
||||
boxWidth < sourceAllocation.x1 - workarea.x)
|
||||
return St.Side.RIGHT;
|
||||
break;
|
||||
case St.Side.RIGHT:
|
||||
if (sourceAllocation.x1 - boxWidth < monitor.x &&
|
||||
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
|
||||
if (sourceAllocation.x1 - boxWidth < workarea.x &&
|
||||
boxWidth < workarea.x + workarea.width - sourceAllocation.x2)
|
||||
return St.Side.LEFT;
|
||||
break;
|
||||
}
|
||||
@@ -667,24 +653,6 @@ var BoxPointer = GObject.registerClass({
|
||||
}
|
||||
}
|
||||
|
||||
set xOffset(offset) {
|
||||
this._xOffset = offset;
|
||||
this._shiftActor();
|
||||
}
|
||||
|
||||
get xOffset() {
|
||||
return this._xOffset;
|
||||
}
|
||||
|
||||
set yOffset(offset) {
|
||||
this._yOffset = offset;
|
||||
this._shiftActor();
|
||||
}
|
||||
|
||||
get yOffset() {
|
||||
return this._yOffset;
|
||||
}
|
||||
|
||||
updateArrowSide(side) {
|
||||
this._arrowSide = side;
|
||||
this._border.queue_repaint();
|
||||
|
@@ -93,10 +93,10 @@ var AutomountManager = class {
|
||||
if (!this._session.SessionIsActive)
|
||||
return;
|
||||
|
||||
let sound = global.display.get_sound();
|
||||
sound.play_from_theme('device-removed-media',
|
||||
_("External drive disconnected"),
|
||||
null);
|
||||
let player = global.display.get_sound_player();
|
||||
player.play_from_theme('device-removed-media',
|
||||
_("External drive disconnected"),
|
||||
null);
|
||||
}
|
||||
|
||||
_onDriveEjectButton(monitor, drive) {
|
||||
|
@@ -94,7 +94,9 @@ var CtrlAltTabManager = class CtrlAltTabManager {
|
||||
if (app)
|
||||
icon = app.create_icon_texture(POPUP_APPICON_SIZE);
|
||||
else
|
||||
icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
|
||||
icon = textureCache.bind_cairo_surface_property(windows[i],
|
||||
'icon',
|
||||
POPUP_APPICON_SIZE);
|
||||
}
|
||||
|
||||
items.push({ name: windows[i].title,
|
||||
|
@@ -584,22 +584,18 @@ var Dash = class Dash {
|
||||
let firstButton = iconChildren[0].child;
|
||||
let firstIcon = firstButton._delegate.icon;
|
||||
|
||||
let minHeight, natHeight;
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
|
||||
// Enforce the current icon size during the size request
|
||||
// Enforce valid spacings during the size request
|
||||
firstIcon.icon.ensure_style();
|
||||
let [, currentHeight] = firstIcon.icon.get_size();
|
||||
firstIcon.icon.set_height(this.iconSize * scaleFactor);
|
||||
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
|
||||
firstIcon.icon.set_height(currentHeight);
|
||||
let [, iconHeight] = firstIcon.icon.get_preferred_height(-1);
|
||||
let [, buttonHeight] = firstButton.get_preferred_height(-1);
|
||||
|
||||
// Subtract icon padding and box spacing from the available height
|
||||
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
|
||||
availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
|
||||
(iconChildren.length - 1) * spacing;
|
||||
|
||||
let availSize = availHeight / iconChildren.length;
|
||||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
|
||||
|
||||
let newIconSize = baseIconSizes[0];
|
||||
|
@@ -136,11 +136,12 @@ var WorldClocksSection = class WorldClocksSection {
|
||||
layout.attach(header, 0, 0, 2, 1);
|
||||
this.actor.label_actor = header;
|
||||
|
||||
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
|
||||
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i].location;
|
||||
|
||||
let name = l.get_level() == GWeather.LocationLevel.NAMED_TIMEZONE ? l.get_name()
|
||||
: l.get_city_name();
|
||||
let name = l.get_city_name() || l.get_name();
|
||||
let label = new St.Label({ style_class: 'world-clocks-city',
|
||||
text: name,
|
||||
x_align: Clutter.ActorAlign.START,
|
||||
@@ -149,7 +150,8 @@ var WorldClocksSection = class WorldClocksSection {
|
||||
|
||||
let time = new St.Label({ style_class: 'world-clocks-time' });
|
||||
|
||||
let offset = l.get_timezone().get_offset() / 60.;
|
||||
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
|
||||
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
|
||||
let fmt = (Math.trunc(offset) == offset) ? '%s%.0f' : '%s%.1f';
|
||||
let prefix = (offset >= 0) ? '+' : '-';
|
||||
let tz = new St.Label({ style_class: 'world-clocks-timezone',
|
||||
@@ -182,11 +184,15 @@ var WorldClocksSection = class WorldClocksSection {
|
||||
}
|
||||
}
|
||||
|
||||
_getTimeAtLocation(location) {
|
||||
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
|
||||
return GLib.DateTime.new_now(tz);
|
||||
}
|
||||
|
||||
_updateLabels() {
|
||||
for (let i = 0; i < this._locations.length; i++) {
|
||||
let l = this._locations[i];
|
||||
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
|
||||
let now = GLib.DateTime.new_now(tz);
|
||||
let now = this._getTimeAtLocation(l.location);
|
||||
l.actor.text = Util.formatTime(now, { timeOnly: true });
|
||||
}
|
||||
}
|
||||
@@ -379,6 +385,7 @@ class IndicatorPad extends St.Widget {
|
||||
_init(actor) {
|
||||
this._source = actor;
|
||||
this._source.connect('notify::visible', () => { this.queue_relayout(); });
|
||||
this._source.connect('notify::size', () => { this.queue_relayout(); });
|
||||
super._init();
|
||||
}
|
||||
|
||||
|
16
js/ui/dnd.js
16
js/ui/dnd.js
@@ -125,6 +125,16 @@ var _Draggable = class _Draggable {
|
||||
}
|
||||
|
||||
_onTouchEvent(actor, event) {
|
||||
// We only handle touch events here on wayland. On X11
|
||||
// we do get emulated pointer events, which already works
|
||||
// for single-touch cases. Besides, the X11 passive touch grab
|
||||
// set up by Mutter will make us see first the touch events
|
||||
// and later the pointer events, so it will look like two
|
||||
// unrelated series of events, we want to avoid double handling
|
||||
// in these cases.
|
||||
if (!Meta.is_wayland_compositor())
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
|
||||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
@@ -296,6 +306,9 @@ var _Draggable = class _Draggable {
|
||||
* for the draggable.
|
||||
*/
|
||||
startDrag(stageX, stageY, time, sequence, device) {
|
||||
if (currentDraggable)
|
||||
return;
|
||||
|
||||
if (device == undefined) {
|
||||
let event = Clutter.get_current_event();
|
||||
|
||||
@@ -437,7 +450,8 @@ var _Draggable = class _Draggable {
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
|
||||
// See if the user has moved the mouse enough to trigger a drag
|
||||
let threshold = St.Settings.get().drag_threshold;
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
let threshold = St.Settings.get().drag_threshold * scaleFactor;
|
||||
if (!currentDraggable &&
|
||||
(Math.abs(stageX - this._dragStartX) > threshold ||
|
||||
Math.abs(stageY - this._dragStartY) > threshold)) {
|
||||
|
@@ -104,6 +104,7 @@ class BaseIcon extends St.Bin {
|
||||
}
|
||||
|
||||
vfunc_style_changed() {
|
||||
super.vfunc_style_changed();
|
||||
let node = this.get_theme_node();
|
||||
|
||||
let size;
|
||||
|
@@ -1,11 +1,16 @@
|
||||
const { Clutter, Gio, GObject, Gtk, Meta, Shell } = imports.gi;
|
||||
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
|
||||
|
||||
const Dialog = imports.ui.dialog;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const PermissionStore = imports.misc.permissionStore;
|
||||
|
||||
const WAYLAND_KEYBINDINGS_SCHEMA = 'org.gnome.mutter.wayland.keybindings';
|
||||
|
||||
const APP_WHITELIST = ['gnome-control-center.desktop'];
|
||||
const APP_PERMISSIONS_TABLE = 'gnome';
|
||||
const APP_PERMISSIONS_ID = 'shortcuts-inhibitor';
|
||||
const GRANTED = 'GRANTED';
|
||||
const DENIED = 'DENIED';
|
||||
|
||||
var DialogResponse = Meta.InhibitShortcutsDialogResponse;
|
||||
|
||||
@@ -43,6 +48,29 @@ var InhibitShortcutsDialog = GObject.registerClass({
|
||||
Gtk.accelerator_parse(accel));
|
||||
}
|
||||
|
||||
_shouldUsePermStore() {
|
||||
return this._app && !this._app.is_window_backed();
|
||||
}
|
||||
|
||||
_saveToPermissionStore(grant) {
|
||||
if (!this._shouldUsePermStore() || this._permStore == null)
|
||||
return;
|
||||
|
||||
let permissions = {};
|
||||
permissions[this._app.get_id()] = [grant];
|
||||
let data = GLib.Variant.new('av', {});
|
||||
|
||||
this._permStore.SetRemote(APP_PERMISSIONS_TABLE,
|
||||
true,
|
||||
APP_PERMISSIONS_ID,
|
||||
permissions,
|
||||
data,
|
||||
(result, error) => {
|
||||
if (error != null)
|
||||
log(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
_buildLayout() {
|
||||
let name = this._app ? this._app.get_name() : this._window.title;
|
||||
|
||||
@@ -64,12 +92,14 @@ var InhibitShortcutsDialog = GObject.registerClass({
|
||||
|
||||
this._dialog.addButton({ label: _("Deny"),
|
||||
action: () => {
|
||||
this._saveToPermissionStore(DENIED);
|
||||
this._emitResponse(DialogResponse.DENY);
|
||||
},
|
||||
key: Clutter.KEY_Escape });
|
||||
|
||||
this._dialog.addButton({ label: _("Allow"),
|
||||
action: () => {
|
||||
this._saveToPermissionStore(GRANTED);
|
||||
this._emitResponse(DialogResponse.ALLOW);
|
||||
},
|
||||
default: true });
|
||||
@@ -81,10 +111,43 @@ var InhibitShortcutsDialog = GObject.registerClass({
|
||||
}
|
||||
|
||||
vfunc_show() {
|
||||
if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1)
|
||||
if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1) {
|
||||
this._emitResponse(DialogResponse.ALLOW);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._shouldUsePermStore()) {
|
||||
this._dialog.open();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check with the permission store */
|
||||
let appId = this._app.get_id();
|
||||
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
|
||||
if (error) {
|
||||
log(error.message);
|
||||
this._dialog.open();
|
||||
return;
|
||||
}
|
||||
|
||||
this._permStore.LookupRemote(APP_PERMISSIONS_TABLE,
|
||||
APP_PERMISSIONS_ID,
|
||||
(res, error) => {
|
||||
if (error) {
|
||||
this._dialog.open();
|
||||
log(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
let [permissions, data] = res;
|
||||
if (permissions[appId] === undefined) // Not found
|
||||
this._dialog.open();
|
||||
else if (permissions[appId] == GRANTED)
|
||||
this._emitResponse(DialogResponse.ALLOW);
|
||||
else
|
||||
this._emitResponse(DialogResponse.DENY);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
vfunc_hide() {
|
||||
|
@@ -73,12 +73,9 @@ class AspectContainer extends St.Widget {
|
||||
box.x1 += Math.floor(diff / 2);
|
||||
box.x2 -= Math.ceil(diff / 2);
|
||||
} else {
|
||||
/* Restrict vertically */
|
||||
/* Restrict vertically, align to bottom */
|
||||
let height = box.get_width() / this._ratio;
|
||||
let diff = box.get_height() - height;
|
||||
|
||||
box.y1 += Math.floor(diff / 2);
|
||||
box.y2 -= Math.floor(diff / 2);
|
||||
box.y1 = box.y2 - Math.floor(height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -884,7 +881,7 @@ var EmojiSelection = class EmojiSelection {
|
||||
this._pageIndicator.setReactive(false);
|
||||
|
||||
let bottomRow = this._createBottomRow();
|
||||
this.actor.add(bottomRow, { x_fill: true, y_fill: false });
|
||||
this.actor.add(bottomRow, { expand: true, x_fill: false, y_fill: false });
|
||||
|
||||
this._emojiPager.setCurrentPage(0);
|
||||
}
|
||||
@@ -973,7 +970,16 @@ var EmojiSelection = class EmojiSelection {
|
||||
row.appendKey(key.actor);
|
||||
row.layoutButtons();
|
||||
|
||||
return row;
|
||||
let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
|
||||
x_expand: true, y_expand: true });
|
||||
actor.add_child(row);
|
||||
/* Regular keyboard layouts are 11.5×4 grids, optimize for that
|
||||
* at the moment. Ideally this should be as wide as the current
|
||||
* keymap.
|
||||
*/
|
||||
actor.setRatio(11.5, 1);
|
||||
|
||||
return actor;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(EmojiSelection.prototype);
|
||||
|
@@ -146,12 +146,13 @@ var MonitorConstraint = GObject.registerClass({
|
||||
});
|
||||
|
||||
var Monitor = class Monitor {
|
||||
constructor(index, geometry) {
|
||||
constructor(index, geometry, geometry_scale) {
|
||||
this.index = index;
|
||||
this.x = geometry.x;
|
||||
this.y = geometry.y;
|
||||
this.width = geometry.width;
|
||||
this.height = geometry.height;
|
||||
this.geometry_scale = geometry_scale;
|
||||
}
|
||||
|
||||
get inFullscreen() {
|
||||
@@ -159,6 +160,19 @@ var Monitor = class Monitor {
|
||||
}
|
||||
};
|
||||
|
||||
const UiActor = GObject.registerClass(
|
||||
class UiActor extends St.Widget {
|
||||
vfunc_get_preferred_width (forHeight) {
|
||||
let width = global.stage.width;
|
||||
return [width, width];
|
||||
}
|
||||
|
||||
vfunc_get_preferred_height (forWidth) {
|
||||
let height = global.stage.height;
|
||||
return [height, height];
|
||||
}
|
||||
});
|
||||
|
||||
const defaultParams = {
|
||||
trackFullscreen: false,
|
||||
affectsStruts: false,
|
||||
@@ -199,12 +213,8 @@ var LayoutManager = GObject.registerClass({
|
||||
global.stage.no_clear_hint = true;
|
||||
|
||||
// Set up stage hierarchy to group all UI actors under one container.
|
||||
this.uiGroup = new St.Widget({ name: 'uiGroup' });
|
||||
this.uiGroup = new UiActor({ name: 'uiGroup' });
|
||||
this.uiGroup.set_flags(Clutter.ActorFlags.NO_LAYOUT);
|
||||
this.uiGroup.add_constraint(new Clutter.BindConstraint({
|
||||
source: global.stage,
|
||||
coordinate: Clutter.BindCoordinate.ALL,
|
||||
}));
|
||||
|
||||
global.stage.remove_actor(global.window_group);
|
||||
this.uiGroup.add_actor(global.window_group);
|
||||
@@ -242,7 +252,7 @@ var LayoutManager = GObject.registerClass({
|
||||
|
||||
// A dummy actor that tracks the mouse or text cursor, based on the
|
||||
// position and size set in setDummyCursorGeometry.
|
||||
this.dummyCursor = new St.Widget({ width: 0, height: 0, visible: false });
|
||||
this.dummyCursor = new St.Widget({ width: 0, height: 0, opacity: 0 });
|
||||
this.uiGroup.add_actor(this.dummyCursor);
|
||||
|
||||
global.stage.remove_actor(global.top_window_group);
|
||||
@@ -318,7 +328,9 @@ var LayoutManager = GObject.registerClass({
|
||||
this.monitors = [];
|
||||
let nMonitors = display.get_n_monitors();
|
||||
for (let i = 0; i < nMonitors; i++)
|
||||
this.monitors.push(new Monitor(i, display.get_monitor_geometry(i)));
|
||||
this.monitors.push(new Monitor(i,
|
||||
display.get_monitor_geometry(i),
|
||||
display.get_monitor_scale(i)));
|
||||
|
||||
if (nMonitors == 0) {
|
||||
this.primaryIndex = this.bottomIndex = -1;
|
||||
|
@@ -382,6 +382,7 @@ var ObjInspector = class ObjInspector {
|
||||
}
|
||||
|
||||
button = new St.Button({ style_class: 'window-close' });
|
||||
button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
|
||||
button.connect('clicked', this.close.bind(this));
|
||||
hbox.add(button);
|
||||
if (typeof(obj) == typeof({})) {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const { Atspi, Clutter, Cogl, GDesktopEnums,
|
||||
const { Atspi, Clutter, GDesktopEnums,
|
||||
Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
@@ -18,9 +18,6 @@ var NO_CHANGE = 0.0;
|
||||
var POINTER_REST_TIME = 1000; // milliseconds
|
||||
|
||||
// Settings
|
||||
const APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
|
||||
const SHOW_KEY = 'screen-magnifier-enabled';
|
||||
|
||||
const MAGNIFIER_SCHEMA = 'org.gnome.desktop.a11y.magnifier';
|
||||
const SCREEN_POSITION_KEY = 'screen-position';
|
||||
const MAG_FACTOR_KEY = 'mag-factor';
|
||||
@@ -56,22 +53,19 @@ var MouseSpriteContent = GObject.registerClass({
|
||||
|
||||
vfunc_get_preferred_size() {
|
||||
if (!this._texture)
|
||||
return [0, 0];
|
||||
return [false, 0, 0];
|
||||
|
||||
return [this._texture.get_width(), this._texture.get_height()];
|
||||
return [true, this._texture.get_width(), this._texture.get_height()];
|
||||
}
|
||||
|
||||
vfunc_paint_content(actor, node) {
|
||||
if (!this._texture)
|
||||
return;
|
||||
|
||||
let color = new Cogl.Color();
|
||||
color.init_from_4ub(0, 0, 0, 0);
|
||||
|
||||
let color = Clutter.Color.get_static(Clutter.StaticColor.WHITE);
|
||||
let [minFilter, magFilter] = actor.get_content_scaling_filters();
|
||||
let textureNode = new Clutter.TextureNode(this._texture,
|
||||
color,
|
||||
Clutter.ScalingFilter.NEAREST,
|
||||
Clutter.ScalingFilter.NEAREST);
|
||||
color, minFilter, magFilter);
|
||||
textureNode.set_name('MouseSpriteContent');
|
||||
node.add_child(textureNode);
|
||||
|
||||
@@ -86,8 +80,14 @@ var MouseSpriteContent = GObject.registerClass({
|
||||
if (this._texture == coglTexture)
|
||||
return;
|
||||
|
||||
let oldTexture = this._texture;
|
||||
this._texture = coglTexture;
|
||||
this.invalidate();
|
||||
|
||||
if (!oldTexture || !coglTexture ||
|
||||
oldTexture.get_width() != coglTexture.get_width() ||
|
||||
oldTexture.get_height() != coglTexture.get_height())
|
||||
this.invalidate_size();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -102,7 +102,6 @@ var Magnifier = class Magnifier {
|
||||
|
||||
this._mouseSprite = new Clutter.Actor({ request_mode: Clutter.RequestMode.CONTENT_SIZE });
|
||||
this._mouseSprite.content = new MouseSpriteContent();
|
||||
this._updateSpriteTexture();
|
||||
|
||||
this._cursorRoot = new Clutter.Actor();
|
||||
this._cursorRoot.add_actor(this._mouseSprite);
|
||||
@@ -115,14 +114,16 @@ var Magnifier = class Magnifier {
|
||||
|
||||
let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
|
||||
this._zoomRegions.push(aZoomRegion);
|
||||
let showAtLaunch = this._settingsInit(aZoomRegion);
|
||||
this._settingsInit(aZoomRegion);
|
||||
aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
|
||||
|
||||
cursorTracker.connect('cursor-changed', this._updateMouseSprite.bind(this));
|
||||
St.Settings.get().connect('notify::magnifier-active', () => {
|
||||
this.setActive(St.Settings.get().magnifier_active);
|
||||
});
|
||||
|
||||
// Export to dbus.
|
||||
magDBusService = new MagnifierDBus.ShellMagnifier();
|
||||
this.setActive(showAtLaunch);
|
||||
this.setActive(St.Settings.get().magnifier_active);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,9 +156,15 @@ var Magnifier = class Magnifier {
|
||||
|
||||
if (isActive != activate) {
|
||||
if (activate) {
|
||||
this._updateMouseSprite();
|
||||
this._cursorSpriteChangedId =
|
||||
this._cursorTracker.connect('cursor-changed',
|
||||
this._updateMouseSprite.bind(this));
|
||||
Meta.disable_unredirect_for_display(global.display);
|
||||
this.startTrackingMouse();
|
||||
} else {
|
||||
this._cursorTracker.disconnect(this._cursorSpriteChangedId);
|
||||
this._mouseSprite.content.texture = null;
|
||||
Meta.enable_unredirect_for_display(global.display);
|
||||
this.stopTrackingMouse();
|
||||
}
|
||||
@@ -495,13 +502,8 @@ var Magnifier = class Magnifier {
|
||||
}
|
||||
|
||||
_settingsInit(zoomRegion) {
|
||||
this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA });
|
||||
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
|
||||
|
||||
this._appSettings.connect('changed::' + SHOW_KEY, () => {
|
||||
this.setActive(this._appSettings.get_boolean(SHOW_KEY));
|
||||
});
|
||||
|
||||
this._settings.connect('changed::' + SCREEN_POSITION_KEY,
|
||||
this._updateScreenPosition.bind(this));
|
||||
this._settings.connect('changed::' + MAG_FACTOR_KEY,
|
||||
@@ -608,8 +610,6 @@ var Magnifier = class Magnifier {
|
||||
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
|
||||
this.addCrosshairs();
|
||||
this.setCrosshairsVisible(showCrosshairs);
|
||||
|
||||
return this._appSettings.get_boolean(SHOW_KEY);
|
||||
}
|
||||
|
||||
_updateScreenPosition() {
|
||||
@@ -756,13 +756,41 @@ var ZoomRegion = class ZoomRegion {
|
||||
|
||||
this._pointerIdleMonitor = Meta.IdleMonitor.get_for_device(Meta.VIRTUAL_CORE_POINTER_ID);
|
||||
this._scrollContentsTimerId = 0;
|
||||
}
|
||||
|
||||
Main.layoutManager.connect('monitors-changed',
|
||||
this._monitorsChanged.bind(this));
|
||||
this._focusCaretTracker.connect('caret-moved',
|
||||
this._updateCaret.bind(this));
|
||||
this._focusCaretTracker.connect('focus-changed',
|
||||
this._updateFocus.bind(this));
|
||||
_connectSignals() {
|
||||
if (this._signalConnections)
|
||||
return;
|
||||
|
||||
this._signalConnections = [];
|
||||
let id = Main.layoutManager.connect('monitors-changed',
|
||||
this._monitorsChanged.bind(this));
|
||||
this._signalConnections.push([Main.layoutManager, id]);
|
||||
|
||||
id = this._focusCaretTracker.connect('caret-moved', this._updateCaret.bind(this));
|
||||
this._signalConnections.push([this._focusCaretTracker, id]);
|
||||
|
||||
id = this._focusCaretTracker.connect('focus-changed', this._updateFocus.bind(this));
|
||||
this._signalConnections.push([this._focusCaretTracker, id]);
|
||||
}
|
||||
|
||||
_disconnectSignals() {
|
||||
for (let [obj, id] of this._signalConnections)
|
||||
obj.disconnect(id);
|
||||
|
||||
delete this._signalConnections;
|
||||
}
|
||||
|
||||
_updateScreenPosition() {
|
||||
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
|
||||
this._setViewPort({
|
||||
x: this._viewPortX,
|
||||
y: this._viewPortY,
|
||||
width: this._viewPortWidth,
|
||||
height: this._viewPortHeight
|
||||
});
|
||||
else
|
||||
this.setScreenPosition(this._screenPosition);
|
||||
}
|
||||
|
||||
_updateFocus(caller, event) {
|
||||
@@ -810,10 +838,13 @@ var ZoomRegion = class ZoomRegion {
|
||||
this._createActors();
|
||||
if (this._isMouseOverRegion())
|
||||
this._magnifier.hideSystemCursor();
|
||||
this._updateScreenPosition();
|
||||
this._updateMagViewGeometry();
|
||||
this._updateCloneGeometry();
|
||||
this._updateMousePosition();
|
||||
this._connectSignals();
|
||||
} else {
|
||||
this._disconnectSignals();
|
||||
this._destroyActors();
|
||||
}
|
||||
|
||||
@@ -1563,18 +1594,8 @@ var ZoomRegion = class ZoomRegion {
|
||||
}
|
||||
|
||||
_monitorsChanged() {
|
||||
if (!this.isActive())
|
||||
return;
|
||||
|
||||
this._background.set_size(global.screen_width, global.screen_height);
|
||||
|
||||
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
|
||||
this._setViewPort({ x: this._viewPortX,
|
||||
y: this._viewPortY,
|
||||
width: this._viewPortWidth,
|
||||
height: this._viewPortHeight });
|
||||
else
|
||||
this.setScreenPosition(this._screenPosition);
|
||||
this._updateScreenPosition();
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -211,13 +211,6 @@ function _initializeUI() {
|
||||
|
||||
_startDate = new Date();
|
||||
|
||||
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
|
||||
if (perfModuleName) {
|
||||
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
|
||||
let module = eval('imports.perf.' + perfModuleName + ';');
|
||||
Scripting.runPerfScript(module, perfOutput);
|
||||
}
|
||||
|
||||
ExtensionDownloader.init();
|
||||
ExtensionSystem.init();
|
||||
|
||||
@@ -239,6 +232,13 @@ function _initializeUI() {
|
||||
Shell.Global.log_structured('GNOME Shell started at ' + _startDate,
|
||||
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
|
||||
}
|
||||
|
||||
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
|
||||
if (perfModuleName) {
|
||||
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
|
||||
let module = eval('imports.perf.' + perfModuleName + ';');
|
||||
Scripting.runPerfScript(module, perfOutput);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -708,6 +708,12 @@ var Source = class Source {
|
||||
return this._policy;
|
||||
}
|
||||
|
||||
set policy(policy) {
|
||||
if (this._policy)
|
||||
this._policy.destroy();
|
||||
this._policy = policy;
|
||||
}
|
||||
|
||||
get count() {
|
||||
return this.notifications.length;
|
||||
}
|
||||
|
@@ -95,28 +95,6 @@ var OsdMonitorLabeler = class {
|
||||
|
||||
this._reset();
|
||||
|
||||
for (let id in params) {
|
||||
let monitor = this._monitorManager.get_monitor_for_output(id);
|
||||
if (monitor == -1)
|
||||
continue;
|
||||
this._monitorLabels.get(monitor).push(params[id].deep_unpack());
|
||||
}
|
||||
|
||||
// In mirrored display setups, more than one physical outputs
|
||||
// might be showing the same logical monitor. In that case, we
|
||||
// join each output's labels on the same OSD widget.
|
||||
for (let [monitor, labels] of this._monitorLabels.entries()) {
|
||||
labels.sort();
|
||||
this._osdLabels.push(new OsdMonitorLabel(monitor, labels.join(' ')));
|
||||
}
|
||||
}
|
||||
|
||||
show2(client, params) {
|
||||
if (!this._trackClient(client))
|
||||
return;
|
||||
|
||||
this._reset();
|
||||
|
||||
for (let connector in params) {
|
||||
let monitor = this._monitorManager.get_monitor_for_connector(connector);
|
||||
if (monitor == -1)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const { Atk, Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
|
||||
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
|
||||
const Cairo = imports.cairo;
|
||||
const Mainloop = imports.mainloop;
|
||||
|
||||
@@ -110,9 +110,14 @@ class AppMenu extends PopupMenu.PopupMenu {
|
||||
});
|
||||
|
||||
this._appSystem.connect('installed-changed', () => {
|
||||
let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
|
||||
this._detailsItem.actor.visible = (sw != null);
|
||||
this._updateDetailsVisibility();
|
||||
});
|
||||
this._updateDetailsVisibility();
|
||||
}
|
||||
|
||||
_updateDetailsVisibility() {
|
||||
let sw = this._appSystem.lookup_app('org.gnome.Software.desktop');
|
||||
this._detailsItem.actor.visible = (sw != null);
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
@@ -196,7 +201,6 @@ var AppMenuButton = GObject.registerClass({
|
||||
this._startingApps = [];
|
||||
|
||||
this._menuManager = panel.menuManager;
|
||||
this._gtkSettings = Gtk.Settings.get_default();
|
||||
this._targetApp = null;
|
||||
this._busyNotifyId = 0;
|
||||
|
||||
@@ -729,7 +733,7 @@ class AggregateLayout extends Clutter.BoxLayout {
|
||||
let child = this._sizeChildren[i];
|
||||
let [childMin, childNat] = child.get_preferred_width(forHeight);
|
||||
minWidth = Math.max(minWidth, childMin);
|
||||
natWidth = Math.max(minWidth, childNat);
|
||||
natWidth = Math.max(natWidth, childNat);
|
||||
}
|
||||
return [minWidth, natWidth];
|
||||
}
|
||||
@@ -804,6 +808,7 @@ class AggregateMenu extends PanelMenu.Button {
|
||||
menuLayout.addSizeChild(this._location.menu.actor);
|
||||
menuLayout.addSizeChild(this._rfkill.menu.actor);
|
||||
menuLayout.addSizeChild(this._power.menu.actor);
|
||||
menuLayout.addSizeChild(this._system.buttonGroup);
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -810,16 +810,8 @@ var ScreenShield = class {
|
||||
|
||||
this._maybeCancelDialog();
|
||||
|
||||
if (this._longLightbox.actor.visible ||
|
||||
this._isActive) {
|
||||
// We're either shown and active, or in the process of
|
||||
// showing.
|
||||
// The latter is a very unlikely condition (it requires
|
||||
// idle-delay < 20), but in any case we have nothing
|
||||
// to do at this point: either isActive is true, or
|
||||
// it will soon be.
|
||||
// isActive can also be true if the lightbox is hidden,
|
||||
// in case the shield is down and the user hasn't unlocked yet
|
||||
if (this._longLightbox.actor.visible) {
|
||||
// We're in the process of showing.
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi;
|
||||
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const GrabHelper = imports.ui.grabHelper;
|
||||
@@ -227,8 +227,6 @@ var SelectArea = class {
|
||||
this._lastY = 0;
|
||||
this._result = null;
|
||||
|
||||
this._initRubberbandColors();
|
||||
|
||||
this._group = new St.Widget({ visible: false,
|
||||
reactive: true,
|
||||
x: 0,
|
||||
@@ -248,10 +246,10 @@ var SelectArea = class {
|
||||
coordinate: Clutter.BindCoordinate.ALL });
|
||||
this._group.add_constraint(constraint);
|
||||
|
||||
this._rubberband = new Clutter.Rectangle({ color: this._background,
|
||||
has_border: true,
|
||||
border_width: 1,
|
||||
border_color: this._border });
|
||||
this._rubberband = new St.Widget({
|
||||
style_class: 'select-area-rubberband',
|
||||
visible: false
|
||||
});
|
||||
this._group.add_actor(this._rubberband);
|
||||
}
|
||||
|
||||
@@ -265,25 +263,6 @@ var SelectArea = class {
|
||||
this._group.visible = true;
|
||||
}
|
||||
|
||||
_initRubberbandColors() {
|
||||
function colorFromRGBA(rgba) {
|
||||
return new Clutter.Color({ red: rgba.red * 255,
|
||||
green: rgba.green * 255,
|
||||
blue: rgba.blue * 255,
|
||||
alpha: rgba.alpha * 255 });
|
||||
}
|
||||
|
||||
let path = new Gtk.WidgetPath();
|
||||
path.append_type(Gtk.IconView);
|
||||
|
||||
let context = new Gtk.StyleContext();
|
||||
context.set_path(path);
|
||||
context.add_class('rubberband');
|
||||
|
||||
this._background = colorFromRGBA(context.get_background_color(Gtk.StateFlags.NORMAL));
|
||||
this._border = colorFromRGBA(context.get_border_color(Gtk.StateFlags.NORMAL));
|
||||
}
|
||||
|
||||
_getGeometry() {
|
||||
return { x: Math.min(this._startX, this._lastX),
|
||||
y: Math.min(this._startY, this._lastY),
|
||||
@@ -302,6 +281,7 @@ var SelectArea = class {
|
||||
|
||||
this._rubberband.set_position(geometry.x, geometry.y);
|
||||
this._rubberband.set_size(geometry.width, geometry.height);
|
||||
this._rubberband.show();
|
||||
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
}
|
||||
|
@@ -37,16 +37,13 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
* 'yield Scripting.sleep(500);'
|
||||
*/
|
||||
function sleep(milliseconds) {
|
||||
let cb;
|
||||
|
||||
let id = Mainloop.timeout_add(milliseconds, () => {
|
||||
if (cb)
|
||||
cb();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
return new Promise(resolve => {
|
||||
let id = Mainloop.timeout_add(milliseconds, () => {
|
||||
resolve();
|
||||
return GLib.SOURCE_REMOVE;
|
||||
});
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] sleep');
|
||||
});
|
||||
GLib.Source.set_name_by_id(id, '[gnome-shell] sleep');
|
||||
|
||||
return callback => { cb = callback; };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,14 +54,9 @@ function sleep(milliseconds) {
|
||||
* 'yield Scripting.waitLeisure();'
|
||||
*/
|
||||
function waitLeisure() {
|
||||
let cb;
|
||||
|
||||
global.run_at_leisure(() => {
|
||||
if (cb)
|
||||
cb();
|
||||
return new Promise(resolve => {
|
||||
global.run_at_leisure(resolve);
|
||||
});
|
||||
|
||||
return callback => { cb = callback; };
|
||||
}
|
||||
|
||||
const PerfHelperIface = loadInterfaceXML('org.gnome.Shell.PerfHelper');
|
||||
@@ -82,25 +74,16 @@ function _getPerfHelper() {
|
||||
}
|
||||
|
||||
function _callRemote(obj, method, ...args) {
|
||||
let cb;
|
||||
let errcb;
|
||||
return new Promise((resolve, reject) => {
|
||||
args.push((result, excp) => {
|
||||
if (excp)
|
||||
reject(excp);
|
||||
else
|
||||
resolve();
|
||||
});
|
||||
|
||||
args.push((result, excp) => {
|
||||
if (excp) {
|
||||
if (errcb)
|
||||
errcb(excp);
|
||||
} else {
|
||||
if (cb)
|
||||
cb();
|
||||
}
|
||||
method.apply(obj, args);
|
||||
});
|
||||
|
||||
method.apply(obj, args);
|
||||
|
||||
return (callback, error_callback) => {
|
||||
cb = callback;
|
||||
errcb = error_callback;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,27 +175,6 @@ function collectStatistics() {
|
||||
Shell.PerfLog.get_default().collect_statistics();
|
||||
}
|
||||
|
||||
function _step(g, finish, onError) {
|
||||
try {
|
||||
let waitFunction = g.next();
|
||||
waitFunction(() => {
|
||||
_step(g, finish, onError);
|
||||
},
|
||||
err => {
|
||||
if (onError)
|
||||
onError(err);
|
||||
});
|
||||
} catch (err) {
|
||||
if (err instanceof StopIteration) {
|
||||
if (finish)
|
||||
finish();
|
||||
} else {
|
||||
if (onError)
|
||||
onError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _collect(scriptModule, outputFile) {
|
||||
let eventHandlers = {};
|
||||
|
||||
@@ -348,23 +310,23 @@ function _collect(scriptModule, outputFile) {
|
||||
* After running the script and collecting statistics from the
|
||||
* event log, GNOME Shell will exit.
|
||||
**/
|
||||
function runPerfScript(scriptModule, outputFile) {
|
||||
async function runPerfScript(scriptModule, outputFile) {
|
||||
Shell.PerfLog.get_default().set_enabled(true);
|
||||
|
||||
let g = scriptModule.run();
|
||||
for (let step of scriptModule.run()) {
|
||||
try {
|
||||
await step;
|
||||
} catch (err) {
|
||||
log(`Script failed: ${err}\n${err.stack}`);
|
||||
Meta.exit(Meta.ExitCode.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
_step(g,
|
||||
() => {
|
||||
try {
|
||||
_collect(scriptModule, outputFile);
|
||||
} catch (err) {
|
||||
log("Script failed: " + err + "\n" + err.stack);
|
||||
Meta.exit(Meta.ExitCode.ERROR);
|
||||
}
|
||||
Meta.exit(Meta.ExitCode.SUCCESS);
|
||||
},
|
||||
err => {
|
||||
log("Script failed: " + err + "\n" + err.stack);
|
||||
Meta.exit(Meta.ExitCode.ERROR);
|
||||
});
|
||||
try {
|
||||
_collect(scriptModule, outputFile);
|
||||
} catch (err) {
|
||||
log(`Script failed: ${err}\n${err.stack}`);
|
||||
Meta.exit(Meta.ExitCode.ERROR);
|
||||
}
|
||||
Meta.exit(Meta.ExitCode.SUCCESS);
|
||||
}
|
||||
|
@@ -79,14 +79,17 @@ var GnomeShell = class {
|
||||
for (let param in params)
|
||||
params[param] = params[param].deep_unpack();
|
||||
|
||||
let { monitor: monitorIndex,
|
||||
let { connector,
|
||||
label,
|
||||
level,
|
||||
max_level: maxLevel,
|
||||
icon: serializedIcon } = params;
|
||||
|
||||
if (monitorIndex === undefined)
|
||||
monitorIndex = -1;
|
||||
let monitorIndex = -1;
|
||||
if (connector) {
|
||||
let monitorManager = Meta.MonitorManager.get();
|
||||
monitorIndex = monitorManager.get_monitor_for_connector(connector);
|
||||
}
|
||||
|
||||
let icon = null;
|
||||
if (serializedIcon)
|
||||
@@ -124,13 +127,20 @@ var GnomeShell = class {
|
||||
|
||||
UngrabAcceleratorAsync(params, invocation) {
|
||||
let [action] = params;
|
||||
let grabbedBy = this._grabbedAccelerators.get(action);
|
||||
if (invocation.get_sender() != grabbedBy)
|
||||
return invocation.return_value(GLib.Variant.new('(b)', [false]));
|
||||
let sender = invocation.get_sender();
|
||||
let ungrabSucceeded = this._ungrabAcceleratorForSender(action, sender);
|
||||
|
||||
return invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
|
||||
}
|
||||
|
||||
UngrabAcceleratorsAsync(params, invocation) {
|
||||
let [actions] = params;
|
||||
let sender = invocation.get_sender();
|
||||
let ungrabSucceeded = true;
|
||||
|
||||
for (let i = 0; i < actions.length; i++)
|
||||
ungrabSucceeded &= this._ungrabAcceleratorForSender(actions[i], sender);
|
||||
|
||||
let ungrabSucceeded = global.display.ungrab_accelerator(action);
|
||||
if (ungrabSucceeded)
|
||||
this._grabbedAccelerators.delete(action);
|
||||
return invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
|
||||
}
|
||||
|
||||
@@ -174,6 +184,16 @@ var GnomeShell = class {
|
||||
let ungrabSucceeded = global.display.ungrab_accelerator(action);
|
||||
if (ungrabSucceeded)
|
||||
this._grabbedAccelerators.delete(action);
|
||||
|
||||
return ungrabSucceeded;
|
||||
}
|
||||
|
||||
_ungrabAcceleratorForSender(action, sender) {
|
||||
let grabbedBy = this._grabbedAccelerators.get(action);
|
||||
if (sender != grabbedBy)
|
||||
return false;
|
||||
|
||||
return this._ungrabAccelerator(action);
|
||||
}
|
||||
|
||||
_onGrabberBusNameVanished(connection, name) {
|
||||
@@ -186,16 +206,10 @@ var GnomeShell = class {
|
||||
this._grabbers.delete(name);
|
||||
}
|
||||
|
||||
ShowMonitorLabelsAsync(params, invocation) {
|
||||
let sender = invocation.get_sender();
|
||||
let [dict] = params;
|
||||
Main.osdMonitorLabeler.show(sender, dict);
|
||||
}
|
||||
|
||||
ShowMonitorLabels2Async(params, invocation) {
|
||||
let sender = invocation.get_sender();
|
||||
let [dict] = params;
|
||||
Main.osdMonitorLabeler.show2(sender, dict);
|
||||
Main.osdMonitorLabeler.show(sender, dict);
|
||||
}
|
||||
|
||||
HideMonitorLabelsAsync(params, invocation) {
|
||||
|
@@ -1236,7 +1236,6 @@ var NMDeviceWireless = class {
|
||||
}
|
||||
|
||||
_dialogClosed() {
|
||||
this._dialog.destroy();
|
||||
this._dialog = null;
|
||||
}
|
||||
|
||||
@@ -1674,7 +1673,11 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
|
||||
_readDevices() {
|
||||
let devices = this._client.get_devices() || [ ];
|
||||
for (let i = 0; i < devices.length; ++i) {
|
||||
this._deviceAdded(this._client, devices[i], true);
|
||||
try {
|
||||
this._deviceAdded(this._client, devices[i], true);
|
||||
} catch (e) {
|
||||
log(`Failed to add device ${devices[i]}: ${e}`);
|
||||
}
|
||||
}
|
||||
this._syncDeviceNames();
|
||||
}
|
||||
|
@@ -236,6 +236,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
|
||||
|
||||
item = new PopupMenu.PopupBaseMenuItem({ reactive: false,
|
||||
can_focus: false });
|
||||
this.buttonGroup = item.actor;
|
||||
|
||||
let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app(
|
||||
'gnome-control-center.desktop'
|
||||
|
@@ -18,7 +18,7 @@ var Avatar = class {
|
||||
this._user = user;
|
||||
params = Params.parse(params, { reactive: false,
|
||||
iconSize: AVATAR_ICON_SIZE,
|
||||
styleClass: 'framed-user-icon' });
|
||||
styleClass: 'user-icon' });
|
||||
this._iconSize = params.iconSize;
|
||||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
@@ -46,15 +46,14 @@ var Avatar = class {
|
||||
if (iconFile) {
|
||||
let file = Gio.File.new_for_path(iconFile);
|
||||
this.actor.child = null;
|
||||
this.actor.style = 'background-image: url("%s");'.format(iconFile);
|
||||
this.actor.style = `
|
||||
background-image: url("${iconFile}");
|
||||
background-size: ${this._iconSize}px`;
|
||||
} else {
|
||||
this.actor.style = null;
|
||||
this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
|
||||
icon_size: this._iconSize });
|
||||
}
|
||||
|
||||
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
||||
this.actor.set_size(this._iconSize * scaleFactor, this._iconSize * scaleFactor);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -101,6 +101,5 @@ var Source = class WindowAttentionSource extends MessageTray.Source {
|
||||
|
||||
open() {
|
||||
Main.activateWindow(this._window);
|
||||
this.destroy();
|
||||
}
|
||||
};
|
||||
|
@@ -456,13 +456,28 @@ var TilePreview = class {
|
||||
};
|
||||
|
||||
var TouchpadWorkspaceSwitchAction = class {
|
||||
constructor(actor) {
|
||||
constructor(actor, allowedModes) {
|
||||
this._allowedModes = allowedModes;
|
||||
this._dx = 0;
|
||||
this._dy = 0;
|
||||
this._enabled = true;
|
||||
actor.connect('captured-event', this._handleEvent.bind(this));
|
||||
this._touchpadSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.peripherals.touchpad'});
|
||||
}
|
||||
|
||||
get enabled() {
|
||||
return this._enabled;
|
||||
}
|
||||
|
||||
set enabled(enabled) {
|
||||
if (this._enabled == enabled)
|
||||
return;
|
||||
|
||||
this._enabled = enabled;
|
||||
if (!enabled)
|
||||
this.emit('cancel');
|
||||
}
|
||||
|
||||
_checkActivated() {
|
||||
let dir;
|
||||
|
||||
@@ -482,15 +497,16 @@ var TouchpadWorkspaceSwitchAction = class {
|
||||
}
|
||||
|
||||
_handleEvent(actor, event) {
|
||||
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
|
||||
|
||||
if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.get_touchpad_gesture_finger_count() != 4)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if ((allowedModes & Main.actionMode) == 0)
|
||||
if ((this._allowedModes & Main.actionMode) == 0)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (!this._enabled)
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
|
||||
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) {
|
||||
@@ -523,10 +539,11 @@ var WorkspaceSwitchAction = GObject.registerClass({
|
||||
'motion': { param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] },
|
||||
'cancel': { param_types: [] }},
|
||||
}, class WorkspaceSwitchAction extends Clutter.SwipeAction {
|
||||
_init() {
|
||||
_init(allowedModes) {
|
||||
super._init();
|
||||
this.set_n_touch_points(4);
|
||||
this._swept = false;
|
||||
this._allowedModes = allowedModes;
|
||||
|
||||
global.display.connect('grab-op-begin', () => {
|
||||
this.cancel();
|
||||
@@ -534,14 +551,12 @@ var WorkspaceSwitchAction = GObject.registerClass({
|
||||
}
|
||||
|
||||
vfunc_gesture_prepare(actor) {
|
||||
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
|
||||
|
||||
this._swept = false;
|
||||
|
||||
if (!super.vfunc_gesture_prepare(actor))
|
||||
return false;
|
||||
|
||||
return (allowedModes & Main.actionMode);
|
||||
return (this._allowedModes & Main.actionMode);
|
||||
}
|
||||
|
||||
vfunc_gesture_progress(actor) {
|
||||
@@ -1043,14 +1058,15 @@ var WindowManager = class {
|
||||
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT,
|
||||
false, -1, 1);
|
||||
|
||||
let gesture = new WorkspaceSwitchAction();
|
||||
let allowedModes = Shell.ActionMode.NORMAL;
|
||||
let gesture = new WorkspaceSwitchAction(allowedModes);
|
||||
gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
|
||||
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
|
||||
gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
|
||||
global.stage.add_action(gesture);
|
||||
|
||||
// This is not a normal Clutter.GestureAction, doesn't need add_action()
|
||||
gesture = new TouchpadWorkspaceSwitchAction(global.stage);
|
||||
gesture = new TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
|
||||
gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
|
||||
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
|
||||
gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
|
||||
@@ -1202,6 +1218,10 @@ var WindowManager = class {
|
||||
// Same for OR windows
|
||||
if (window.is_override_redirect())
|
||||
return;
|
||||
// Sticky windows don't need moving, in fact moving would
|
||||
// unstick them
|
||||
if (window.on_all_workspaces)
|
||||
return;
|
||||
// Windows on workspaces below pos don't need moving
|
||||
let index = window.get_workspace().index();
|
||||
if (index < pos)
|
||||
|
@@ -1,10 +1,11 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
|
||||
const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const WindowManager = imports.ui.windowManager;
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
var WORKSPACE_SWITCH_TIME = 0.25;
|
||||
@@ -82,6 +83,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||
|
||||
this._animating = false; // tweening
|
||||
this._scrolling = false; // swipe-scrolling
|
||||
this._gestureActive = false; // touch(pad) gestures
|
||||
this._animatingScroll = false; // programatically updating the adjustment
|
||||
|
||||
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
|
||||
@@ -211,7 +213,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||
|
||||
for (let w = 0; w < this._workspaces.length; w++) {
|
||||
let workspace = this._workspaces[w];
|
||||
if (this._animating || this._scrolling) {
|
||||
if (this._animating || this._scrolling || this._gestureActive) {
|
||||
workspace.actor.show();
|
||||
} else {
|
||||
if (this._inDrag)
|
||||
@@ -223,7 +225,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||
}
|
||||
|
||||
_updateScrollAdjustment(index) {
|
||||
if (this._scrolling)
|
||||
if (this._scrolling || this._gestureActive)
|
||||
return;
|
||||
|
||||
this._animatingScroll = true;
|
||||
@@ -300,6 +302,18 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||
this._updateVisibility();
|
||||
}
|
||||
|
||||
startTouchGesture() {
|
||||
this._gestureActive = true;
|
||||
}
|
||||
|
||||
endTouchGesture() {
|
||||
this._gestureActive = false;
|
||||
|
||||
// Make sure title captions etc are shown as necessary
|
||||
this._scrollToActive();
|
||||
this._updateVisibility();
|
||||
}
|
||||
|
||||
// sync the workspaces' positions to the value of the scroll adjustment
|
||||
// and change the active workspace if appropriate
|
||||
_onScroll(adj) {
|
||||
@@ -310,7 +324,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
|
||||
let active = workspaceManager.get_active_workspace_index();
|
||||
let current = Math.round(adj.value);
|
||||
|
||||
if (active != current) {
|
||||
if (active != current && !this._gestureActive) {
|
||||
if (!this._workspaces[current]) {
|
||||
// The current workspace was destroyed. This could happen
|
||||
// when you are on the last empty workspace, and consolidate
|
||||
@@ -391,6 +405,12 @@ var ExtraWorkspaceView = class extends WorkspacesViewBase {
|
||||
|
||||
endSwipeScroll() {
|
||||
}
|
||||
|
||||
startTouchGesture() {
|
||||
}
|
||||
|
||||
endTouchGesture() {
|
||||
}
|
||||
};
|
||||
|
||||
var DelegateFocusNavigator = GObject.registerClass(
|
||||
@@ -430,23 +450,37 @@ var WorkspacesDisplay = class {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].startSwipeScroll();
|
||||
this._startSwipeScroll();
|
||||
return true;
|
||||
});
|
||||
panAction.connect('gesture-cancel', () => {
|
||||
clickAction.release();
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].endSwipeScroll();
|
||||
this._endSwipeScroll();
|
||||
});
|
||||
panAction.connect('gesture-end', () => {
|
||||
clickAction.release();
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].endSwipeScroll();
|
||||
this._endSwipeScroll();
|
||||
});
|
||||
Main.overview.addAction(panAction);
|
||||
this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
let allowedModes = Shell.ActionMode.OVERVIEW;
|
||||
let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
|
||||
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
|
||||
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
|
||||
switchGesture.connect('cancel', this._endTouchGesture.bind(this));
|
||||
Main.overview.addAction(switchGesture);
|
||||
this.actor.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
|
||||
|
||||
switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
|
||||
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
|
||||
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
|
||||
switchGesture.connect('cancel', this._endTouchGesture.bind(this));
|
||||
this.actor.connect('notify::mapped', () => {
|
||||
switchGesture.enabled = this.actor.mapped;
|
||||
});
|
||||
switchGesture.enabled = this.actor.mapped;
|
||||
|
||||
this._primaryIndex = Main.layoutManager.primaryIndex;
|
||||
|
||||
this._workspacesViews = [];
|
||||
@@ -474,6 +508,47 @@ var WorkspacesDisplay = class {
|
||||
return false;
|
||||
}
|
||||
|
||||
_startSwipeScroll() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].startSwipeScroll();
|
||||
}
|
||||
|
||||
_endSwipeScroll() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].endSwipeScroll();
|
||||
}
|
||||
|
||||
_startTouchGesture() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].startTouchGesture();
|
||||
}
|
||||
|
||||
_endTouchGesture() {
|
||||
for (let i = 0; i < this._workspacesViews.length; i++)
|
||||
this._workspacesViews[i].endTouchGesture();
|
||||
}
|
||||
|
||||
_onSwitchWorkspaceMotion(action, xRel, yRel) {
|
||||
// We don't have a way to hook into start of touchpad actions,
|
||||
// luckily this is safe to call repeatedly.
|
||||
this._startTouchGesture();
|
||||
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let active = workspaceManager.get_active_workspace_index();
|
||||
let adjustment = this._scrollAdjustment;
|
||||
adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
|
||||
}
|
||||
|
||||
_onSwitchWorkspaceActivated(action, direction) {
|
||||
let workspaceManager = global.workspace_manager;
|
||||
let activeWorkspace = workspaceManager.get_active_workspace();
|
||||
let newWs = activeWorkspace.get_neighbor(direction);
|
||||
if (newWs != activeWorkspace)
|
||||
newWs.activate(global.get_current_time());
|
||||
|
||||
this._endTouchGesture();
|
||||
}
|
||||
|
||||
navigateFocus(from, direction) {
|
||||
return this._getPrimaryView().actor.navigate_focus(from, direction, false);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('gnome-shell', 'c',
|
||||
version: '3.31.91',
|
||||
version: '3.32.0',
|
||||
meson_version: '>= 0.47.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
@@ -20,10 +20,10 @@ gcr_req = '>= 3.7.5'
|
||||
gdesktop_req = '>= 3.7.90'
|
||||
gio_req = '>= 2.56.0'
|
||||
gi_req = '>= 1.49.1'
|
||||
gjs_req = '>= 1.47.0'
|
||||
gjs_req = '>= 1.54.0'
|
||||
gtk_req = '>= 3.15.0'
|
||||
json_glib_req = '>= 0.13.2'
|
||||
mutter_req = '>= 3.31.91'
|
||||
mutter_req = '>= 3.32.0'
|
||||
polkit_req = '>= 0.100'
|
||||
schemas_req = '>= 3.27.90'
|
||||
startup_req = '>= 0.11'
|
||||
|
2
po/af.po
2
po/af.po
@@ -330,7 +330,7 @@ msgstr "Netwerkaanmelding"
|
||||
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
|
||||
#: data/org.gnome.Shell.PortalHelper.desktop.in.in:9
|
||||
msgid "network-workgroup"
|
||||
msgstr "netwerk-werkgroep"
|
||||
msgstr "network-workgroup"
|
||||
|
||||
#: js/extensionPrefs/main.js:120
|
||||
#, javascript-format
|
||||
|
1043
po/en_GB.po
1043
po/en_GB.po
File diff suppressed because it is too large
Load Diff
52
po/id.po
52
po/id.po
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
|
||||
"POT-Creation-Date: 2019-02-11 18:01+0000\n"
|
||||
"POT-Creation-Date: 2019-02-21 18:43+0000\n"
|
||||
"PO-Revision-Date: 2019-02-14 22:18+0700\n"
|
||||
"Last-Translator: Kukuh Syafaat <kukuhsyafaat@gnome.org>\n"
|
||||
"Language-Team: Indonesian <gnome-l10n-id@googlegroups.com>\n"
|
||||
@@ -480,7 +480,7 @@ msgstr "Jendela Log Masuk"
|
||||
|
||||
#: js/gdm/util.js:337
|
||||
msgid "Authentication error"
|
||||
msgstr "Galat otentikasi"
|
||||
msgstr "Galat autentikasi"
|
||||
|
||||
#. We don't show fingerprint messages directly since it's
|
||||
#. not the main auth service. Instead we use the messages
|
||||
@@ -748,12 +748,12 @@ msgstr "Tambah ke Favorit"
|
||||
msgid "Show Details"
|
||||
msgstr "Tampilkan Rincian"
|
||||
|
||||
#: js/ui/appFavorites.js:139
|
||||
#: js/ui/appFavorites.js:141
|
||||
#, javascript-format
|
||||
msgid "%s has been added to your favorites."
|
||||
msgstr "%s telah ditambahkan ke favorit Anda."
|
||||
|
||||
#: js/ui/appFavorites.js:173
|
||||
#: js/ui/appFavorites.js:175
|
||||
#, javascript-format
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s telah dihapus dari favorit Anda."
|
||||
@@ -791,7 +791,7 @@ msgid "Settings"
|
||||
msgstr "Pengaturan"
|
||||
|
||||
#. Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday).
|
||||
#: js/ui/calendar.js:38
|
||||
#: js/ui/calendar.js:40
|
||||
msgctxt "calendar-no-work"
|
||||
msgid "06"
|
||||
msgstr "06"
|
||||
@@ -801,43 +801,43 @@ msgstr "06"
|
||||
#. * NOTE: These grid abbreviations are always shown together
|
||||
#. * and in order, e.g. "S M T W T F S".
|
||||
#.
|
||||
#: js/ui/calendar.js:67
|
||||
#: js/ui/calendar.js:69
|
||||
msgctxt "grid sunday"
|
||||
msgid "S"
|
||||
msgstr "M"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Monday
|
||||
#: js/ui/calendar.js:69
|
||||
#: js/ui/calendar.js:71
|
||||
msgctxt "grid monday"
|
||||
msgid "M"
|
||||
msgstr "S"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Tuesday
|
||||
#: js/ui/calendar.js:71
|
||||
#: js/ui/calendar.js:73
|
||||
msgctxt "grid tuesday"
|
||||
msgid "T"
|
||||
msgstr "S"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Wednesday
|
||||
#: js/ui/calendar.js:73
|
||||
#: js/ui/calendar.js:75
|
||||
msgctxt "grid wednesday"
|
||||
msgid "W"
|
||||
msgstr "R"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Thursday
|
||||
#: js/ui/calendar.js:75
|
||||
#: js/ui/calendar.js:77
|
||||
msgctxt "grid thursday"
|
||||
msgid "T"
|
||||
msgstr "K"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Friday
|
||||
#: js/ui/calendar.js:77
|
||||
#: js/ui/calendar.js:79
|
||||
msgctxt "grid friday"
|
||||
msgid "F"
|
||||
msgstr "J"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Saturday
|
||||
#: js/ui/calendar.js:79
|
||||
#: js/ui/calendar.js:81
|
||||
msgctxt "grid saturday"
|
||||
msgid "S"
|
||||
msgstr "S"
|
||||
@@ -848,7 +848,7 @@ msgstr "S"
|
||||
#. * "%OB" is the new format specifier introduced in glibc 2.27,
|
||||
#. * in most cases you should not change it.
|
||||
#.
|
||||
#: js/ui/calendar.js:342
|
||||
#: js/ui/calendar.js:332
|
||||
msgid "%OB"
|
||||
msgstr "%OB"
|
||||
|
||||
@@ -861,55 +861,55 @@ msgstr "%OB"
|
||||
#. * in most cases you should not use the old "%B" here unless you
|
||||
#. * absolutely know what you are doing.
|
||||
#.
|
||||
#: js/ui/calendar.js:352
|
||||
#: js/ui/calendar.js:342
|
||||
msgid "%OB %Y"
|
||||
msgstr "%OB %Y"
|
||||
|
||||
#: js/ui/calendar.js:409
|
||||
#: js/ui/calendar.js:399
|
||||
msgid "Previous month"
|
||||
msgstr "Bulan sebelumnya"
|
||||
|
||||
#: js/ui/calendar.js:420
|
||||
#: js/ui/calendar.js:410
|
||||
msgid "Next month"
|
||||
msgstr "Bulan selanjutnya"
|
||||
|
||||
#: js/ui/calendar.js:574
|
||||
#: js/ui/calendar.js:564
|
||||
#, no-javascript-format
|
||||
msgctxt "date day number format"
|
||||
msgid "%d"
|
||||
msgstr "%d"
|
||||
|
||||
#: js/ui/calendar.js:629
|
||||
#: js/ui/calendar.js:619
|
||||
msgid "Week %V"
|
||||
msgstr "Minggu %V"
|
||||
|
||||
#. Translators: Shown in calendar event list for all day events
|
||||
#. * Keep it short, best if you can use less then 10 characters
|
||||
#.
|
||||
#: js/ui/calendar.js:697
|
||||
#: js/ui/calendar.js:687
|
||||
msgctxt "event list time"
|
||||
msgid "All Day"
|
||||
msgstr "Sepanjang Hari"
|
||||
|
||||
#: js/ui/calendar.js:829
|
||||
#: js/ui/calendar.js:819
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %-d"
|
||||
msgstr "%A, %d %B"
|
||||
|
||||
#: js/ui/calendar.js:833
|
||||
#: js/ui/calendar.js:823
|
||||
msgctxt "calendar heading"
|
||||
msgid "%A, %B %-d, %Y"
|
||||
msgstr "%A, %d %B %Y"
|
||||
|
||||
#: js/ui/calendar.js:1056
|
||||
#: js/ui/calendar.js:1046
|
||||
msgid "No Notifications"
|
||||
msgstr "Tak Ada Pemberitahuan"
|
||||
|
||||
#: js/ui/calendar.js:1059
|
||||
#: js/ui/calendar.js:1049
|
||||
msgid "No Events"
|
||||
msgstr "Tak Ada Kejadian"
|
||||
|
||||
#: js/ui/calendar.js:1085
|
||||
#: js/ui/calendar.js:1075
|
||||
msgid "Clear"
|
||||
msgstr "Bersihkan"
|
||||
|
||||
@@ -1045,7 +1045,7 @@ msgstr "Manajer Jaringan"
|
||||
|
||||
#: js/ui/components/polkitAgent.js:34
|
||||
msgid "Authentication Required"
|
||||
msgstr "Diperlukan Otentikasi"
|
||||
msgstr "Diperlukan Autentikasi"
|
||||
|
||||
#: js/ui/components/polkitAgent.js:62
|
||||
msgid "Administrator"
|
||||
@@ -2266,7 +2266,7 @@ msgstr "Sandi tidak boleh kosong"
|
||||
|
||||
#: src/shell-polkit-authentication-agent.c:348
|
||||
msgid "Authentication dialog was dismissed by the user"
|
||||
msgstr "Dialog otentikasi ditolak oleh pengguna"
|
||||
msgstr "Dialog autentikasi ditolak oleh pengguna"
|
||||
|
||||
#. translators:
|
||||
#. * The number of sound outputs on a particular device
|
||||
|
1007
po/zh_TW.po
1007
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,16 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* GnomeShellPlugin is the entry point for for GNOME Shell into and out of
|
||||
* Mutter. By registering itself into Mutter using
|
||||
* meta_plugin_manager_set_plugin_type(), Mutter will call the vfuncs of the
|
||||
* plugin at the appropriate time.
|
||||
*
|
||||
* The funcions in in GnomeShellPlugin are all just stubs, which just call the
|
||||
* similar methods in GnomeShellWm.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -37,72 +47,10 @@
|
||||
#include "shell-perf-log.h"
|
||||
#include "shell-wm-private.h"
|
||||
|
||||
static void gnome_shell_plugin_start (MetaPlugin *plugin);
|
||||
static void gnome_shell_plugin_minimize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void gnome_shell_plugin_unminimize (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void gnome_shell_plugin_size_changed (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void gnome_shell_plugin_size_change (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
MetaSizeChange which_change,
|
||||
MetaRectangle *old_frame_rect,
|
||||
MetaRectangle *old_buffer_rect);
|
||||
static void gnome_shell_plugin_map (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void gnome_shell_plugin_destroy (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
|
||||
static void gnome_shell_plugin_switch_workspace (MetaPlugin *plugin,
|
||||
gint from,
|
||||
gint to,
|
||||
MetaMotionDirection direction);
|
||||
|
||||
static void gnome_shell_plugin_kill_window_effects (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
static void gnome_shell_plugin_kill_switch_workspace (MetaPlugin *plugin);
|
||||
|
||||
static void gnome_shell_plugin_show_tile_preview (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaRectangle *tile_rect,
|
||||
int tile_monitor);
|
||||
static void gnome_shell_plugin_hide_tile_preview (MetaPlugin *plugin);
|
||||
static void gnome_shell_plugin_show_window_menu (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
int x,
|
||||
int y);
|
||||
static void gnome_shell_plugin_show_window_menu_for_rect (MetaPlugin *plugin,
|
||||
MetaWindow *window,
|
||||
MetaWindowMenuType menu,
|
||||
MetaRectangle *rect);
|
||||
|
||||
static gboolean gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
|
||||
XEvent *event);
|
||||
|
||||
static gboolean gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
static void gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin);
|
||||
|
||||
static const MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin);
|
||||
|
||||
static MetaCloseDialog * gnome_shell_plugin_create_close_dialog (MetaPlugin *plugin,
|
||||
MetaWindow *window);
|
||||
|
||||
static MetaInhibitShortcutsDialog * gnome_shell_plugin_create_inhibit_shortcuts_dialog (MetaPlugin *plugin,
|
||||
MetaWindow *window);
|
||||
|
||||
#define GNOME_TYPE_SHELL_PLUGIN (gnome_shell_plugin_get_type ())
|
||||
#define GNOME_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPlugin))
|
||||
#define GNOME_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
|
||||
#define GNOME_IS_SHELL_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_SHELL_PLUGIN_TYPE))
|
||||
#define GNOME_IS_SHELL_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_SHELL_PLUGIN))
|
||||
#define GNOME_SHELL_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_SHELL_PLUGIN, GnomeShellPluginClass))
|
||||
|
||||
typedef struct _GnomeShellPlugin GnomeShellPlugin;
|
||||
typedef struct _GnomeShellPluginClass GnomeShellPluginClass;
|
||||
#define GNOME_TYPE_SHELL_PLUGIN (gnome_shell_plugin_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GnomeShellPlugin, gnome_shell_plugin,
|
||||
GNOME, SHELL_PLUGIN,
|
||||
MetaPlugin)
|
||||
|
||||
struct _GnomeShellPlugin
|
||||
{
|
||||
@@ -116,54 +64,8 @@ struct _GnomeShellPlugin
|
||||
ShellGlobal *global;
|
||||
};
|
||||
|
||||
struct _GnomeShellPluginClass
|
||||
{
|
||||
MetaPluginClass parent_class;
|
||||
};
|
||||
|
||||
GType gnome_shell_plugin_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GnomeShellPlugin, gnome_shell_plugin, META_TYPE_PLUGIN)
|
||||
|
||||
static void
|
||||
gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
|
||||
{
|
||||
MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass);
|
||||
|
||||
plugin_class->start = gnome_shell_plugin_start;
|
||||
plugin_class->map = gnome_shell_plugin_map;
|
||||
plugin_class->minimize = gnome_shell_plugin_minimize;
|
||||
plugin_class->unminimize = gnome_shell_plugin_unminimize;
|
||||
plugin_class->size_changed = gnome_shell_plugin_size_changed;
|
||||
plugin_class->size_change = gnome_shell_plugin_size_change;
|
||||
plugin_class->destroy = gnome_shell_plugin_destroy;
|
||||
|
||||
plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
|
||||
|
||||
plugin_class->kill_window_effects = gnome_shell_plugin_kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
|
||||
|
||||
plugin_class->show_tile_preview = gnome_shell_plugin_show_tile_preview;
|
||||
plugin_class->hide_tile_preview = gnome_shell_plugin_hide_tile_preview;
|
||||
plugin_class->show_window_menu = gnome_shell_plugin_show_window_menu;
|
||||
plugin_class->show_window_menu_for_rect = gnome_shell_plugin_show_window_menu_for_rect;
|
||||
|
||||
plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter;
|
||||
plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
|
||||
|
||||
plugin_class->confirm_display_change = gnome_shell_plugin_confirm_display_change;
|
||||
|
||||
plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
|
||||
|
||||
plugin_class->create_close_dialog = gnome_shell_plugin_create_close_dialog;
|
||||
plugin_class->create_inhibit_shortcuts_dialog = gnome_shell_plugin_create_inhibit_shortcuts_dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnome_shell_plugin_has_swap_event (GnomeShellPlugin *shell_plugin)
|
||||
{
|
||||
@@ -416,8 +318,8 @@ gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin)
|
||||
_shell_wm_confirm_display_change (get_shell_wm ());
|
||||
}
|
||||
|
||||
static const
|
||||
MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
|
||||
static const MetaPluginInfo *
|
||||
gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
|
||||
{
|
||||
static const MetaPluginInfo info = {
|
||||
.name = "GNOME Shell",
|
||||
@@ -443,3 +345,42 @@ gnome_shell_plugin_create_inhibit_shortcuts_dialog (MetaPlugin *plugin,
|
||||
{
|
||||
return _shell_wm_create_inhibit_shortcuts_dialog (get_shell_wm (), window);
|
||||
}
|
||||
|
||||
static void
|
||||
gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
|
||||
{
|
||||
MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass);
|
||||
|
||||
plugin_class->start = gnome_shell_plugin_start;
|
||||
plugin_class->map = gnome_shell_plugin_map;
|
||||
plugin_class->minimize = gnome_shell_plugin_minimize;
|
||||
plugin_class->unminimize = gnome_shell_plugin_unminimize;
|
||||
plugin_class->size_changed = gnome_shell_plugin_size_changed;
|
||||
plugin_class->size_change = gnome_shell_plugin_size_change;
|
||||
plugin_class->destroy = gnome_shell_plugin_destroy;
|
||||
|
||||
plugin_class->switch_workspace = gnome_shell_plugin_switch_workspace;
|
||||
|
||||
plugin_class->kill_window_effects = gnome_shell_plugin_kill_window_effects;
|
||||
plugin_class->kill_switch_workspace = gnome_shell_plugin_kill_switch_workspace;
|
||||
|
||||
plugin_class->show_tile_preview = gnome_shell_plugin_show_tile_preview;
|
||||
plugin_class->hide_tile_preview = gnome_shell_plugin_hide_tile_preview;
|
||||
plugin_class->show_window_menu = gnome_shell_plugin_show_window_menu;
|
||||
plugin_class->show_window_menu_for_rect = gnome_shell_plugin_show_window_menu_for_rect;
|
||||
|
||||
plugin_class->xevent_filter = gnome_shell_plugin_xevent_filter;
|
||||
plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
|
||||
|
||||
plugin_class->confirm_display_change = gnome_shell_plugin_confirm_display_change;
|
||||
|
||||
plugin_class->plugin_info = gnome_shell_plugin_plugin_info;
|
||||
|
||||
plugin_class->create_close_dialog = gnome_shell_plugin_create_close_dialog;
|
||||
plugin_class->create_inhibit_shortcuts_dialog = gnome_shell_plugin_create_inhibit_shortcuts_dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
|
||||
{
|
||||
}
|
||||
|
@@ -184,7 +184,7 @@ window_backed_app_get_icon (ShellApp *app,
|
||||
int size)
|
||||
{
|
||||
MetaWindow *window = NULL;
|
||||
ClutterActor *actor;
|
||||
StWidget *widget;
|
||||
gint scale;
|
||||
ShellGlobal *global;
|
||||
StThemeContext *context;
|
||||
@@ -204,16 +204,20 @@ window_backed_app_get_icon (ShellApp *app,
|
||||
|
||||
if (window == NULL)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_new ();
|
||||
g_object_set (actor, "opacity", 0, "width", (float) size, "height", (float) size, NULL);
|
||||
return actor;
|
||||
}
|
||||
|
||||
actor = st_texture_cache_bind_cairo_surface_property (st_texture_cache_get_default (),
|
||||
G_OBJECT (window),
|
||||
"icon");
|
||||
g_object_set (actor, "width", (float) size, "height", (float) size, NULL);
|
||||
return actor;
|
||||
widget = st_texture_cache_bind_cairo_surface_property (st_texture_cache_get_default (),
|
||||
G_OBJECT (window),
|
||||
"icon",
|
||||
size);
|
||||
st_widget_add_style_class_name (widget, "fallback-app-icon");
|
||||
|
||||
return CLUTTER_ACTOR (widget);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1179,13 +1183,26 @@ _shell_app_handle_startup_sequence (ShellApp *app,
|
||||
gboolean
|
||||
shell_app_request_quit (ShellApp *app)
|
||||
{
|
||||
GActionGroup *group = NULL;
|
||||
GSList *iter;
|
||||
|
||||
if (shell_app_get_state (app) != SHELL_APP_STATE_RUNNING)
|
||||
return FALSE;
|
||||
|
||||
/* TODO - check for an XSMP connection; we could probably use that */
|
||||
/* First, check whether the app exports an explicit "quit" action
|
||||
* that we can activate on the bus
|
||||
*/
|
||||
group = G_ACTION_GROUP (app->running_state->muxer);
|
||||
|
||||
if (g_action_group_has_action (group, "app.quit") &&
|
||||
g_action_group_get_action_parameter_type (group, "app.quit") == NULL)
|
||||
{
|
||||
g_action_group_activate_action (group, "app.quit", NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Otherwise, fall back to closing all the app's windows */
|
||||
for (iter = app->running_state->windows; iter; iter = iter->next)
|
||||
{
|
||||
MetaWindow *win = iter->data;
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "shell-embedded-window-private.h"
|
||||
#include "shell-global.h"
|
||||
#include "shell-util.h"
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
#include <meta/display.h>
|
||||
@@ -94,6 +95,10 @@ shell_gtk_embed_window_created_cb (MetaDisplay *display,
|
||||
as a normal window */
|
||||
clutter_actor_set_opacity (window_actor, 0);
|
||||
|
||||
/* Also make sure it (or any of its children) doesn't block
|
||||
events on wayland */
|
||||
shell_util_set_hidden_from_pick (window_actor, TRUE);
|
||||
|
||||
/* Set an empty input shape on the window so that it can't get
|
||||
any input. This probably isn't the ideal way to achieve this.
|
||||
It would probably be better to force the window to go behind
|
||||
|
@@ -17,15 +17,13 @@
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <meta/display.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include <st/st.h>
|
||||
|
||||
#include "shell-global.h"
|
||||
#include "shell-recorder-src.h"
|
||||
#include "shell-recorder.h"
|
||||
#include "shell-util.h"
|
||||
|
||||
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
|
||||
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
|
||||
|
||||
typedef enum {
|
||||
RECORDER_STATE_CLOSED,
|
||||
RECORDER_STATE_RECORDING
|
||||
@@ -51,10 +49,13 @@ struct _ShellRecorder {
|
||||
int stage_width;
|
||||
int stage_height;
|
||||
|
||||
int capture_width;
|
||||
int capture_height;
|
||||
float scale;
|
||||
|
||||
int pointer_x;
|
||||
int pointer_y;
|
||||
|
||||
GSettings *a11y_settings;
|
||||
gboolean draw_cursor;
|
||||
MetaCursorTracker *cursor_tracker;
|
||||
cairo_surface_t *cursor_image;
|
||||
@@ -209,8 +210,6 @@ shell_recorder_init (ShellRecorder *recorder)
|
||||
|
||||
recorder->memory_target = get_memory_target();
|
||||
|
||||
recorder->a11y_settings = g_settings_new (A11Y_APPS_SCHEMA);
|
||||
|
||||
recorder->state = RECORDER_STATE_CLOSED;
|
||||
recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
|
||||
recorder->draw_cursor = TRUE;
|
||||
@@ -235,8 +234,6 @@ shell_recorder_finalize (GObject *object)
|
||||
|
||||
recorder_remove_redraw_timeout (recorder);
|
||||
|
||||
g_clear_object (&recorder->a11y_settings);
|
||||
|
||||
G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
@@ -430,10 +427,8 @@ recorder_record_frame (ShellRecorder *recorder,
|
||||
return;
|
||||
recorder->last_frame_time = now;
|
||||
|
||||
clutter_stage_capture (recorder->stage, paint, &recorder->area,
|
||||
&captures, &n_captures);
|
||||
|
||||
if (n_captures == 0)
|
||||
if (!clutter_stage_capture (recorder->stage, paint, &recorder->area,
|
||||
&captures, &n_captures))
|
||||
return;
|
||||
|
||||
if (n_captures == 1)
|
||||
@@ -443,8 +438,9 @@ recorder_record_frame (ShellRecorder *recorder,
|
||||
n_captures,
|
||||
recorder->area.x,
|
||||
recorder->area.y,
|
||||
recorder->area.width,
|
||||
recorder->area.height);
|
||||
recorder->capture_width,
|
||||
recorder->capture_height,
|
||||
recorder->scale);
|
||||
|
||||
data = cairo_image_surface_get_data (image);
|
||||
size = (cairo_image_surface_get_height (image) *
|
||||
@@ -462,9 +458,16 @@ recorder_record_frame (ShellRecorder *recorder,
|
||||
|
||||
GST_BUFFER_PTS(buffer) = now;
|
||||
|
||||
if (recorder->draw_cursor &&
|
||||
!g_settings_get_boolean (recorder->a11y_settings, MAGNIFIER_ACTIVE_KEY))
|
||||
recorder_draw_cursor (recorder, buffer);
|
||||
if (recorder->draw_cursor)
|
||||
{
|
||||
StSettings *settings = st_settings_get ();
|
||||
gboolean magnifier_active = FALSE;
|
||||
|
||||
g_object_get (settings, "magnifier-active", &magnifier_active, NULL);
|
||||
|
||||
if (magnifier_active)
|
||||
recorder_draw_cursor (recorder, buffer);
|
||||
}
|
||||
|
||||
shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer);
|
||||
gst_buffer_unref (buffer);
|
||||
@@ -500,6 +503,11 @@ recorder_update_size (ShellRecorder *recorder)
|
||||
recorder->area.y = 0;
|
||||
recorder->area.width = recorder->stage_width;
|
||||
recorder->area.height = recorder->stage_height;
|
||||
|
||||
clutter_stage_get_capture_final_size (recorder->stage, NULL,
|
||||
&recorder->capture_width,
|
||||
&recorder->capture_height,
|
||||
&recorder->scale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,6 +626,8 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
|
||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||
g_signal_connect (recorder->stage, "notify::height",
|
||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||
g_signal_connect (recorder->stage, "notify::resource-scale",
|
||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -875,6 +885,7 @@ shell_recorder_class_init (ShellRecorderClass *klass)
|
||||
static void
|
||||
recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
||||
{
|
||||
ShellRecorder *recorder = pipeline->recorder;
|
||||
GstCaps *caps;
|
||||
|
||||
/* The data is always native-endian xRGB; videoconvert
|
||||
@@ -887,9 +898,9 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
||||
#else
|
||||
"format", G_TYPE_STRING, "xRGB",
|
||||
#endif
|
||||
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
|
||||
"width", G_TYPE_INT, pipeline->recorder->area.width,
|
||||
"height", G_TYPE_INT, pipeline->recorder->area.height,
|
||||
"framerate", GST_TYPE_FRACTION, recorder->framerate, 1,
|
||||
"width", G_TYPE_INT, recorder->capture_width,
|
||||
"height", G_TYPE_INT, recorder->capture_height,
|
||||
NULL);
|
||||
g_object_set (pipeline->src, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
@@ -1496,6 +1507,11 @@ shell_recorder_set_area (ShellRecorder *recorder,
|
||||
recorder->area.height = CLAMP (height,
|
||||
0, recorder->stage_height - recorder->area.y);
|
||||
|
||||
clutter_stage_get_capture_final_size (recorder->stage, &recorder->area,
|
||||
&recorder->capture_width,
|
||||
&recorder->capture_height,
|
||||
&recorder->scale);
|
||||
|
||||
/* This breaks the recording but tweaking the GStreamer pipeline a bit
|
||||
* might make it work, at least if the codec can handle a stream where
|
||||
* the frame size changes in the middle.
|
||||
|
@@ -7,14 +7,12 @@
|
||||
#include <meta/meta-plugin.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/meta-cursor-tracker.h>
|
||||
#include <st/st.h>
|
||||
|
||||
#include "shell-global.h"
|
||||
#include "shell-screenshot.h"
|
||||
#include "shell-util.h"
|
||||
|
||||
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
|
||||
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
|
||||
|
||||
typedef struct _ShellScreenshotPrivate ShellScreenshotPrivate;
|
||||
|
||||
struct _ShellScreenshot
|
||||
@@ -40,6 +38,13 @@ struct _ShellScreenshotPrivate
|
||||
gboolean include_frame;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SHELL_SCREENSHOT_SCREEN,
|
||||
SHELL_SCREENSHOT_WINDOW,
|
||||
SHELL_SCREENSHOT_AREA,
|
||||
} ShellScreenshotMode;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
@@ -195,6 +200,9 @@ write_screenshot_thread (GTask *result,
|
||||
cairo_image_surface_get_height (priv->image));
|
||||
creation_time = g_date_time_format (priv->datetime, "%c");
|
||||
|
||||
if (!creation_time)
|
||||
creation_time = g_date_time_format (priv->datetime, "%FT%T%z");
|
||||
|
||||
if (gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, NULL,
|
||||
"tEXt::Software", "gnome-screenshot",
|
||||
"tEXt::Creation Time", creation_time,
|
||||
@@ -222,29 +230,32 @@ do_grab_screenshot (ShellScreenshot *screenshot,
|
||||
int height)
|
||||
{
|
||||
ShellScreenshotPrivate *priv = screenshot->priv;
|
||||
cairo_rectangle_int_t screenshot_rect = { x, y, width, height };
|
||||
ClutterCapture *captures;
|
||||
int n_captures;
|
||||
int i;
|
||||
|
||||
clutter_stage_capture (stage, FALSE,
|
||||
&(cairo_rectangle_int_t) {
|
||||
.x = x,
|
||||
.y = y,
|
||||
.width = width,
|
||||
.height = height
|
||||
},
|
||||
&captures,
|
||||
&n_captures);
|
||||
|
||||
if (n_captures == 0)
|
||||
if (!clutter_stage_capture (stage, FALSE,
|
||||
&screenshot_rect,
|
||||
&captures,
|
||||
&n_captures))
|
||||
return;
|
||||
else if (n_captures == 1)
|
||||
|
||||
if (n_captures == 1)
|
||||
priv->image = cairo_surface_reference (captures[0].image);
|
||||
else
|
||||
priv->image = shell_util_composite_capture_images (captures,
|
||||
n_captures,
|
||||
x, y,
|
||||
width, height);
|
||||
{
|
||||
float target_scale;
|
||||
|
||||
clutter_stage_get_capture_final_size (stage, &screenshot_rect,
|
||||
&width, &height, &target_scale);
|
||||
priv->image = shell_util_composite_capture_images (captures,
|
||||
n_captures,
|
||||
x, y,
|
||||
width, height,
|
||||
target_scale);
|
||||
}
|
||||
|
||||
priv->datetime = g_date_time_new_now_local ();
|
||||
|
||||
for (i = 0; i < n_captures; i++)
|
||||
@@ -253,22 +264,44 @@ do_grab_screenshot (ShellScreenshot *screenshot,
|
||||
g_free (captures);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
should_draw_cursor_image (ShellScreenshotMode mode)
|
||||
{
|
||||
if (mode == SHELL_SCREENSHOT_WINDOW || !meta_is_wayland_compositor ())
|
||||
{
|
||||
StSettings *settings = st_settings_get ();
|
||||
gboolean magnifier_active = FALSE;
|
||||
|
||||
g_object_get (settings, "magnifier-active", &magnifier_active, NULL);
|
||||
|
||||
if (!magnifier_active)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_draw_cursor_image (MetaCursorTracker *tracker,
|
||||
cairo_surface_t *surface,
|
||||
cairo_rectangle_int_t area)
|
||||
draw_cursor_image (cairo_surface_t *surface,
|
||||
cairo_rectangle_int_t area)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
int width, height;
|
||||
int stride;
|
||||
guint8 *data;
|
||||
MetaDisplay *display;
|
||||
MetaCursorTracker *tracker;
|
||||
cairo_surface_t *cursor_surface;
|
||||
cairo_region_t *screenshot_region;
|
||||
cairo_t *cr;
|
||||
int x, y;
|
||||
int xhot, yhot;
|
||||
double xscale, yscale;
|
||||
|
||||
display = shell_global_get_display (shell_global_get ());
|
||||
tracker = meta_cursor_tracker_get_for_display (display);
|
||||
texture = meta_cursor_tracker_get_sprite (tracker);
|
||||
|
||||
if (!texture)
|
||||
return;
|
||||
|
||||
@@ -294,6 +327,22 @@ _draw_cursor_image (MetaCursorTracker *tracker,
|
||||
width, height,
|
||||
stride);
|
||||
|
||||
cairo_surface_get_device_scale (surface, &xscale, &yscale);
|
||||
|
||||
if (xscale != 1.0 || yscale != 1.0)
|
||||
{
|
||||
int monitor;
|
||||
float monitor_scale;
|
||||
MetaRectangle cursor_rect = {
|
||||
.x = x, .y = y, .width = width, .height = height
|
||||
};
|
||||
|
||||
monitor = meta_display_get_monitor_index_for_rect (display, &cursor_rect);
|
||||
monitor_scale = meta_display_get_monitor_scale (display, monitor);
|
||||
|
||||
cairo_surface_set_device_scale (cursor_surface, monitor_scale, monitor_scale);
|
||||
}
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_source_surface (cr,
|
||||
cursor_surface,
|
||||
@@ -312,9 +361,7 @@ grab_screenshot (ClutterActor *stage,
|
||||
GTask *result)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
MetaCursorTracker *tracker;
|
||||
int width, height;
|
||||
GSettings *settings;
|
||||
ShellScreenshot *screenshot = g_task_get_source_object (result);
|
||||
ShellScreenshotPrivate *priv = screenshot->priv;
|
||||
GTask *task;
|
||||
@@ -368,14 +415,8 @@ grab_screenshot (ClutterActor *stage,
|
||||
priv->screenshot_area.width = width;
|
||||
priv->screenshot_area.height = height;
|
||||
|
||||
settings = g_settings_new (A11Y_APPS_SCHEMA);
|
||||
if (priv->include_cursor &&
|
||||
!g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY))
|
||||
{
|
||||
tracker = meta_cursor_tracker_get_for_display (display);
|
||||
_draw_cursor_image (tracker, priv->image, priv->screenshot_area);
|
||||
}
|
||||
g_object_unref (settings);
|
||||
if (priv->include_cursor)
|
||||
draw_cursor_image (priv->image, priv->screenshot_area);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (stage, grab_screenshot, result);
|
||||
|
||||
@@ -412,9 +453,7 @@ grab_window_screenshot (ClutterActor *stage,
|
||||
ShellScreenshot *screenshot = g_task_get_source_object (result);
|
||||
ShellScreenshotPrivate *priv = screenshot->priv;
|
||||
GTask *task;
|
||||
GSettings *settings;
|
||||
MetaDisplay *display = shell_global_get_display (priv->global);
|
||||
MetaCursorTracker *tracker;
|
||||
MetaWindow *window = meta_display_get_focus_window (display);
|
||||
ClutterActor *window_actor;
|
||||
gfloat actor_x, actor_y;
|
||||
@@ -442,13 +481,19 @@ grab_window_screenshot (ClutterActor *stage,
|
||||
priv->image = meta_shaped_texture_get_image (stex, &clip);
|
||||
priv->datetime = g_date_time_new_now_local ();
|
||||
|
||||
settings = g_settings_new (A11Y_APPS_SCHEMA);
|
||||
if (priv->include_cursor && !g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY))
|
||||
if (priv->include_cursor)
|
||||
{
|
||||
tracker = meta_cursor_tracker_get_for_display (display);
|
||||
_draw_cursor_image (tracker, priv->image, priv->screenshot_area);
|
||||
if (meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
float resource_scale;
|
||||
if (!clutter_actor_get_resource_scale (window_actor, &resource_scale))
|
||||
resource_scale = 1.0f;
|
||||
|
||||
cairo_surface_set_device_scale (priv->image, resource_scale, resource_scale);
|
||||
}
|
||||
|
||||
draw_cursor_image (priv->image, priv->screenshot_area);
|
||||
}
|
||||
g_object_unref (settings);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (stage, grab_window_screenshot, result);
|
||||
task = g_task_new (screenshot, NULL, on_screenshot_written, result);
|
||||
@@ -520,6 +565,7 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ShellScreenshotPrivate *priv = screenshot->priv;
|
||||
const char *paint_signal;
|
||||
GTask *result;
|
||||
|
||||
if (priv->filename != NULL) {
|
||||
@@ -539,13 +585,22 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
|
||||
g_task_set_source_tag (result, shell_screenshot_screenshot);
|
||||
|
||||
priv->filename = g_strdup (filename);
|
||||
priv->include_cursor = include_cursor;
|
||||
priv->include_cursor = FALSE;
|
||||
|
||||
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
|
||||
paint_signal = "actors-painted";
|
||||
|
||||
meta_disable_unredirect_for_display (shell_global_get_display (priv->global));
|
||||
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), result);
|
||||
if (include_cursor)
|
||||
{
|
||||
if (should_draw_cursor_image (SHELL_SCREENSHOT_SCREEN))
|
||||
priv->include_cursor = TRUE;
|
||||
else
|
||||
paint_signal = "paint";
|
||||
}
|
||||
|
||||
g_signal_connect_after (stage, paint_signal, G_CALLBACK (grab_screenshot), result);
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
}
|
||||
@@ -634,7 +689,7 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
|
||||
|
||||
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
|
||||
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), result);
|
||||
g_signal_connect_after (stage, "actors-painted", G_CALLBACK (grab_area_screenshot), result);
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
}
|
||||
@@ -713,13 +768,14 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
|
||||
|
||||
priv->filename = g_strdup (filename);
|
||||
priv->include_frame = include_frame;
|
||||
priv->include_cursor = include_cursor;
|
||||
priv->include_cursor = include_cursor &&
|
||||
should_draw_cursor_image (SHELL_SCREENSHOT_WINDOW);
|
||||
|
||||
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
|
||||
|
||||
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
|
||||
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), result);
|
||||
g_signal_connect_after (stage, "actors-painted", G_CALLBACK (grab_window_screenshot), result);
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
}
|
||||
@@ -787,7 +843,7 @@ shell_screenshot_pick_color (ShellScreenshot *screenshot,
|
||||
|
||||
meta_disable_unredirect_for_display (display);
|
||||
|
||||
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_pixel), result);
|
||||
g_signal_connect_after (stage, "actors-painted", G_CALLBACK (grab_pixel), result);
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
}
|
||||
|
@@ -77,13 +77,13 @@ shell_tray_icon_constructed (GObject *object)
|
||||
plug_xid = GDK_WINDOW_XID (icon_app_window);
|
||||
|
||||
display = gtk_widget_get_display (GTK_WIDGET (icon->priv->socket));
|
||||
gdk_error_trap_push ();
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
_NET_WM_PID = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID");
|
||||
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), plug_xid,
|
||||
_NET_WM_PID, 0, G_MAXLONG, False, XA_CARDINAL,
|
||||
&type, &format, &nitems,
|
||||
&bytes_after, (guchar **)&val);
|
||||
if (!gdk_error_trap_pop () &&
|
||||
if (!gdk_x11_display_error_trap_pop (display) &&
|
||||
result == Success &&
|
||||
type == XA_CARDINAL &&
|
||||
nitems == 1)
|
||||
@@ -190,6 +190,7 @@ shell_tray_icon_click (ShellTrayIcon *icon,
|
||||
XKeyEvent xkevent;
|
||||
XButtonEvent xbevent;
|
||||
XCrossingEvent xcevent;
|
||||
GdkDisplay *display;
|
||||
GdkWindow *remote_window;
|
||||
GdkScreen *screen;
|
||||
int x_root, y_root;
|
||||
@@ -201,21 +202,23 @@ shell_tray_icon_click (ShellTrayIcon *icon,
|
||||
event_type == CLUTTER_KEY_PRESS ||
|
||||
event_type == CLUTTER_KEY_RELEASE);
|
||||
|
||||
gdk_error_trap_push ();
|
||||
|
||||
remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket));
|
||||
if (remote_window == NULL)
|
||||
{
|
||||
g_warning ("shell tray: plug window is gone");
|
||||
gdk_error_trap_pop_ignored ();
|
||||
return;
|
||||
}
|
||||
xwindow = GDK_WINDOW_XID (remote_window);
|
||||
xdisplay = GDK_WINDOW_XDISPLAY (remote_window);
|
||||
|
||||
display = gdk_x11_lookup_xdisplay (xdisplay);
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
|
||||
xwindow = GDK_WINDOW_XID (remote_window);
|
||||
screen = gdk_window_get_screen (remote_window);
|
||||
xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen));
|
||||
gdk_window_get_origin (remote_window, &x_root, &y_root);
|
||||
|
||||
|
||||
/* First make the icon believe the pointer is inside it */
|
||||
xcevent.type = EnterNotify;
|
||||
xcevent.window = xwindow;
|
||||
@@ -287,5 +290,5 @@ shell_tray_icon_click (ShellTrayIcon *icon,
|
||||
xcevent.type = LeaveNotify;
|
||||
XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent);
|
||||
|
||||
gdk_error_trap_pop_ignored ();
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
}
|
||||
|
@@ -212,13 +212,7 @@ void
|
||||
shell_tray_manager_manage_screen (ShellTrayManager *manager,
|
||||
StWidget *theme_widget)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkScreen *gdk_screen;
|
||||
|
||||
display = gdk_display_get_default ();
|
||||
gdk_screen = gdk_display_get_default_screen (display);
|
||||
|
||||
na_tray_manager_manage_screen (manager->priv->na_manager, gdk_screen);
|
||||
na_tray_manager_manage_screen (manager->priv->na_manager);
|
||||
|
||||
g_signal_connect_object (theme_widget, "style-changed",
|
||||
G_CALLBACK (shell_tray_manager_style_changed),
|
||||
@@ -245,8 +239,10 @@ shell_tray_manager_child_on_realize (GtkWidget *widget,
|
||||
bg_pattern = cairo_pattern_create_rgb (color.red / 255.,
|
||||
color.green / 255.,
|
||||
color.blue / 255.);
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
gdk_window_set_background_pattern (gtk_widget_get_window (widget),
|
||||
bg_pattern);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
cairo_pattern_destroy (bg_pattern);
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -434,14 +435,23 @@ shell_util_get_content_for_window_actor (MetaWindowActor *window_actor,
|
||||
cairo_surface_t *surface;
|
||||
cairo_rectangle_int_t clip;
|
||||
gfloat actor_x, actor_y;
|
||||
gfloat resource_scale;
|
||||
|
||||
texture = meta_window_actor_get_texture (window_actor);
|
||||
clutter_actor_get_position (CLUTTER_ACTOR (window_actor), &actor_x, &actor_y);
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (window_actor),
|
||||
&resource_scale))
|
||||
{
|
||||
resource_scale = 1.0;
|
||||
g_warning ("Actor resource scale is not know at this point, "
|
||||
"falling back to default 1.0");
|
||||
}
|
||||
|
||||
clip.x = window_rect->x - (gint) actor_x;
|
||||
clip.y = window_rect->y - (gint) actor_y;
|
||||
clip.width = window_rect->width;
|
||||
clip.height = window_rect->height;
|
||||
clip.width = ceilf (window_rect->width * resource_scale);
|
||||
clip.height = ceilf (window_rect->height * resource_scale);
|
||||
|
||||
surface = meta_shaped_texture_get_image (META_SHAPED_TEXTURE (texture),
|
||||
&clip);
|
||||
@@ -462,31 +472,20 @@ shell_util_composite_capture_images (ClutterCapture *captures,
|
||||
int n_captures,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
int target_width,
|
||||
int target_height,
|
||||
float target_scale)
|
||||
{
|
||||
int i;
|
||||
double target_scale;
|
||||
cairo_format_t format;
|
||||
cairo_surface_t *image;
|
||||
cairo_t *cr;
|
||||
|
||||
g_assert (n_captures > 0);
|
||||
|
||||
target_scale = 0.0;
|
||||
for (i = 0; i < n_captures; i++)
|
||||
{
|
||||
ClutterCapture *capture = &captures[i];
|
||||
double capture_scale = 1.0;
|
||||
|
||||
cairo_surface_get_device_scale (capture->image, &capture_scale, NULL);
|
||||
target_scale = MAX (target_scale, capture_scale);
|
||||
}
|
||||
g_assert (target_scale > 0.0f);
|
||||
|
||||
format = cairo_image_surface_get_format (captures[0].image);
|
||||
image = cairo_image_surface_create (format,
|
||||
width * target_scale,
|
||||
height * target_scale);
|
||||
image = cairo_image_surface_create (format, target_width, target_height);
|
||||
cairo_surface_set_device_scale (image, target_scale, target_scale);
|
||||
|
||||
cr = cairo_create (image);
|
||||
|
@@ -53,8 +53,9 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures
|
||||
int n_captures,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
int target_width,
|
||||
int target_height,
|
||||
float target_scale);
|
||||
|
||||
void shell_util_check_cloexec_fds (void);
|
||||
|
||||
|
@@ -12,6 +12,7 @@ st_headers = [
|
||||
'st-generic-accessible.h',
|
||||
'st-icon.h',
|
||||
'st-icon-colors.h',
|
||||
'st-image-content.h',
|
||||
'st-label.h',
|
||||
'st-private.h',
|
||||
'st-scrollable.h',
|
||||
@@ -66,6 +67,7 @@ st_sources = [
|
||||
'st-generic-accessible.c',
|
||||
'st-icon.c',
|
||||
'st-icon-colors.c',
|
||||
'st-image-content.c',
|
||||
'st-label.c',
|
||||
'st-private.c',
|
||||
'st-scrollable.c',
|
||||
@@ -124,6 +126,7 @@ libst = shared_library('st-1.0',
|
||||
sources: st_gir_sources + st_non_gir_sources,
|
||||
c_args: st_cflags,
|
||||
dependencies: [clutter_dep, gtk_dep, croco_dep, x11_dep, m_dep],
|
||||
build_rpath: mutter_typelibdir,
|
||||
install_rpath: mutter_typelibdir,
|
||||
install_dir: pkglibdir,
|
||||
install: true
|
||||
@@ -137,9 +140,14 @@ test_theme = executable('test-theme',
|
||||
sources: 'test-theme.c',
|
||||
c_args: st_cflags,
|
||||
dependencies: [clutter_dep, gtk_dep],
|
||||
build_rpath: mutter_typelibdir,
|
||||
link_with: libst
|
||||
)
|
||||
|
||||
test('CSS styling support', test_theme,
|
||||
workdir: meson.current_source_dir()
|
||||
)
|
||||
|
||||
libst_gir = gnome.generate_gir(libst,
|
||||
sources: st_gir_sources,
|
||||
nsversion: '1.0',
|
||||
|
@@ -58,32 +58,6 @@ static Atom __atom_clip = None;
|
||||
static Atom __utf8_string = None;
|
||||
static Atom __atom_targets = None;
|
||||
|
||||
static void
|
||||
st_clipboard_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_clipboard_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (property_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_clipboard_dispose (GObject *object)
|
||||
{
|
||||
@@ -180,8 +154,6 @@ st_clipboard_class_init (StClipboardClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = st_clipboard_get_property;
|
||||
object_class->set_property = st_clipboard_set_property;
|
||||
object_class->dispose = st_clipboard_dispose;
|
||||
object_class->finalize = st_clipboard_finalize;
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "st-drawing-area.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef struct _StDrawingAreaPrivate StDrawingAreaPrivate;
|
||||
struct _StDrawingAreaPrivate {
|
||||
@@ -84,12 +85,22 @@ st_drawing_area_allocate (ClutterActor *self,
|
||||
ClutterContent *content = clutter_actor_get_content (self);
|
||||
ClutterActorBox content_box;
|
||||
int width, height;
|
||||
float resource_scale;
|
||||
|
||||
if (!st_widget_get_resource_scale (ST_WIDGET (self), &resource_scale))
|
||||
{
|
||||
ClutterActorBox empty = CLUTTER_ACTOR_BOX_INIT_ZERO;
|
||||
clutter_actor_set_allocation (self, &empty, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_actor_set_allocation (self, box, flags);
|
||||
st_theme_node_get_content_box (theme_node, box, &content_box);
|
||||
|
||||
width = (int)(0.5 + content_box.x2 - content_box.x1);
|
||||
height = (int)(0.5 + content_box.y2 - content_box.y1);
|
||||
|
||||
clutter_canvas_set_scale_factor (CLUTTER_CANVAS (content), resource_scale);
|
||||
clutter_canvas_set_size (CLUTTER_CANVAS (content), width, height);
|
||||
}
|
||||
|
||||
@@ -101,6 +112,16 @@ st_drawing_area_style_changed (StWidget *self)
|
||||
st_drawing_area_queue_repaint (ST_DRAWING_AREA (self));
|
||||
}
|
||||
|
||||
static void
|
||||
st_drawing_area_resource_scale_changed (StWidget *self)
|
||||
{
|
||||
float resource_scale;
|
||||
ClutterContent *content = clutter_actor_get_content (CLUTTER_ACTOR (self));
|
||||
|
||||
if (st_widget_get_resource_scale (ST_WIDGET (self), &resource_scale))
|
||||
clutter_canvas_set_scale_factor (CLUTTER_CANVAS (content), resource_scale);
|
||||
}
|
||||
|
||||
static void
|
||||
st_drawing_area_class_init (StDrawingAreaClass *klass)
|
||||
{
|
||||
@@ -109,6 +130,7 @@ st_drawing_area_class_init (StDrawingAreaClass *klass)
|
||||
|
||||
actor_class->allocate = st_drawing_area_allocate;
|
||||
widget_class->style_changed = st_drawing_area_style_changed;
|
||||
widget_class->resource_scale_changed = st_drawing_area_resource_scale_changed;
|
||||
|
||||
st_drawing_area_signals[REPAINT] =
|
||||
g_signal_new ("repaint",
|
||||
@@ -185,7 +207,7 @@ st_drawing_area_get_surface_size (StDrawingArea *area,
|
||||
{
|
||||
StDrawingAreaPrivate *priv;
|
||||
ClutterContent *content;
|
||||
float w, h;
|
||||
float w, h, resource_scale;
|
||||
|
||||
g_return_if_fail (ST_IS_DRAWING_AREA (area));
|
||||
|
||||
@@ -195,8 +217,18 @@ st_drawing_area_get_surface_size (StDrawingArea *area,
|
||||
content = clutter_actor_get_content (CLUTTER_ACTOR (area));
|
||||
clutter_content_get_preferred_size (content, &w, &h);
|
||||
|
||||
if (st_widget_get_resource_scale (ST_WIDGET (area), &resource_scale))
|
||||
{
|
||||
w /= resource_scale;
|
||||
h /= resource_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
w = h = 0.0f;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = (guint)w;
|
||||
*width = ceilf (w);
|
||||
if (height)
|
||||
*height = (guint)h;
|
||||
*height = ceilf (h);
|
||||
}
|
||||
|
@@ -210,6 +210,12 @@ st_icon_style_changed (StWidget *widget)
|
||||
st_icon_update (self);
|
||||
}
|
||||
|
||||
static void
|
||||
st_icon_resource_scale_changed (StWidget *widget)
|
||||
{
|
||||
st_icon_update (ST_ICON (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
st_icon_class_init (StIconClass *klass)
|
||||
{
|
||||
@@ -226,6 +232,7 @@ st_icon_class_init (StIconClass *klass)
|
||||
actor_class->paint = st_icon_paint;
|
||||
|
||||
widget_class->style_changed = st_icon_style_changed;
|
||||
widget_class->resource_scale_changed = st_icon_resource_scale_changed;
|
||||
|
||||
pspec = g_param_spec_object ("gicon",
|
||||
"GIcon",
|
||||
@@ -344,6 +351,8 @@ st_icon_finish_update (StIcon *icon)
|
||||
g_signal_connect_object (priv->icon_texture, "notify::content",
|
||||
G_CALLBACK (on_content_changed), icon, 0);
|
||||
}
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (icon));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -366,9 +375,10 @@ st_icon_update (StIcon *icon)
|
||||
StIconPrivate *priv = icon->priv;
|
||||
StThemeNode *theme_node;
|
||||
StTextureCache *cache;
|
||||
gint scale;
|
||||
gint paint_scale;
|
||||
ClutterActor *stage;
|
||||
StThemeContext *context;
|
||||
float resource_scale;
|
||||
|
||||
if (priv->pending_texture)
|
||||
{
|
||||
@@ -378,13 +388,16 @@ st_icon_update (StIcon *icon)
|
||||
priv->opacity_handler_id = 0;
|
||||
}
|
||||
|
||||
if (!st_widget_get_resource_scale (ST_WIDGET (icon), &resource_scale))
|
||||
return;
|
||||
|
||||
theme_node = st_widget_peek_theme_node (ST_WIDGET (icon));
|
||||
if (theme_node == NULL)
|
||||
return;
|
||||
|
||||
stage = clutter_actor_get_stage (CLUTTER_ACTOR (icon));
|
||||
context = st_theme_context_get_for_stage (CLUTTER_STAGE (stage));
|
||||
g_object_get (context, "scale-factor", &scale, NULL);
|
||||
g_object_get (context, "scale-factor", &paint_scale, NULL);
|
||||
|
||||
cache = st_texture_cache_get_default ();
|
||||
|
||||
@@ -393,14 +406,16 @@ st_icon_update (StIcon *icon)
|
||||
theme_node,
|
||||
priv->gicon,
|
||||
priv->icon_size,
|
||||
scale);
|
||||
paint_scale,
|
||||
resource_scale);
|
||||
|
||||
if (priv->pending_texture == NULL && priv->fallback_gicon != NULL)
|
||||
priv->pending_texture = st_texture_cache_load_gicon (cache,
|
||||
theme_node,
|
||||
priv->fallback_gicon,
|
||||
priv->icon_size,
|
||||
scale);
|
||||
paint_scale,
|
||||
resource_scale);
|
||||
|
||||
if (priv->pending_texture)
|
||||
{
|
||||
|
191
src/st/st-image-content.c
Normal file
191
src/st/st-image-content.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* st-image-content.h: A content image with scaling support
|
||||
*
|
||||
* Copyright 2019 Canonical, Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "st-image-content.h"
|
||||
|
||||
struct _StImageContent
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterImage parent_instance;
|
||||
};
|
||||
|
||||
typedef struct _StImageContentPrivate StImageContentPrivate;
|
||||
struct _StImageContentPrivate
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_PREFERRED_WIDTH,
|
||||
PROP_PREFERRED_HEIGHT,
|
||||
};
|
||||
|
||||
static void clutter_content_interface_init (ClutterContentInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (StImageContent, st_image_content, CLUTTER_TYPE_IMAGE,
|
||||
G_ADD_PRIVATE (StImageContent)
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
|
||||
clutter_content_interface_init))
|
||||
|
||||
static void
|
||||
st_image_content_init (StImageContent *self)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
st_image_content_constructed (GObject *object)
|
||||
{
|
||||
StImageContent *self = ST_IMAGE_CONTENT (object);
|
||||
StImageContentPrivate *priv = st_image_content_get_instance_private (self);
|
||||
|
||||
if (priv->width < 0 || priv->height < 0)
|
||||
g_warning ("StImageContent initialized with invalid preferred size: %dx%d\n",
|
||||
priv->width, priv->height);
|
||||
}
|
||||
|
||||
static void
|
||||
st_image_content_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
StImageContent *self = ST_IMAGE_CONTENT (object);
|
||||
StImageContentPrivate *priv = st_image_content_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PREFERRED_WIDTH:
|
||||
g_value_set_int (value, priv->width);
|
||||
break;
|
||||
|
||||
case PROP_PREFERRED_HEIGHT:
|
||||
g_value_set_int (value, priv->height);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_image_content_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
StImageContent *self = ST_IMAGE_CONTENT (object);
|
||||
StImageContentPrivate *priv = st_image_content_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PREFERRED_WIDTH:
|
||||
priv->width = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_PREFERRED_HEIGHT:
|
||||
priv->height = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_image_content_class_init (StImageContentClass *klass)
|
||||
{
|
||||
GParamSpec *pspec;
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = st_image_content_constructed;
|
||||
object_class->get_property = st_image_content_get_property;
|
||||
object_class->set_property = st_image_content_set_property;
|
||||
|
||||
pspec = g_param_spec_int ("preferred-width",
|
||||
"Preferred Width",
|
||||
"Preferred Width of the Content when painted",
|
||||
-1, G_MAXINT, -1,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_PREFERRED_WIDTH, pspec);
|
||||
|
||||
pspec = g_param_spec_int ("preferred-height",
|
||||
"Preferred Height",
|
||||
"Preferred Height of the Content when painted",
|
||||
-1, G_MAXINT, -1,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
||||
g_object_class_install_property (object_class, PROP_PREFERRED_HEIGHT, pspec);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
st_image_content_get_preferred_size (ClutterContent *content,
|
||||
float *width,
|
||||
float *height)
|
||||
{
|
||||
StImageContent *self = ST_IMAGE_CONTENT (content);
|
||||
StImageContentPrivate *priv = st_image_content_get_instance_private (self);
|
||||
ClutterTexture *texture;
|
||||
|
||||
texture = clutter_image_get_texture (CLUTTER_IMAGE (content));
|
||||
|
||||
if (texture == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_assert_cmpint (priv->width, >, -1);
|
||||
g_assert_cmpint (priv->height, >, -1);
|
||||
|
||||
if (width != NULL)
|
||||
*width = (float) priv->width;
|
||||
|
||||
if (height != NULL)
|
||||
*height = (float) priv->height;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_interface_init (ClutterContentInterface *iface)
|
||||
{
|
||||
iface->get_preferred_size = st_image_content_get_preferred_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* st_image_content_new_with_preferred_size:
|
||||
* @width: The preferred width to be used when drawing the content
|
||||
* @height: The preferred width to be used when drawing the content
|
||||
*
|
||||
* Creates a new #StImageContent, a simple content for sized images.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #StImageContent content
|
||||
* Use g_object_unref() when done.
|
||||
*/
|
||||
ClutterContent *
|
||||
st_image_content_new_with_preferred_size (int width,
|
||||
int height)
|
||||
{
|
||||
return g_object_new (ST_TYPE_IMAGE_CONTENT,
|
||||
"preferred-width", width,
|
||||
"preferred-height", height,
|
||||
NULL);
|
||||
}
|
33
src/st/st-image-content.h
Normal file
33
src/st/st-image-content.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* st-image-content.h: A content image with scaling support
|
||||
*
|
||||
* Copyright 2019 Canonical, Ltd
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation, either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __ST_IMAGE_CONTENT_H__
|
||||
#define __ST_IMAGE_CONTENT_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define ST_TYPE_IMAGE_CONTENT (st_image_content_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (StImageContent, st_image_content,
|
||||
ST, IMAGE_CONTENT, ClutterImage)
|
||||
|
||||
ClutterContent *st_image_content_new_with_preferred_size (int width,
|
||||
int height);
|
||||
|
||||
#endif /* __ST_IMAGE_CONTENT_H__ */
|
@@ -197,34 +197,52 @@ st_label_paint (ClutterActor *actor)
|
||||
|
||||
if (shadow_spec)
|
||||
{
|
||||
ClutterActorBox allocation;
|
||||
float width, height;
|
||||
float resource_scale;
|
||||
|
||||
clutter_actor_get_allocation_box (priv->label, &allocation);
|
||||
clutter_actor_box_get_size (&allocation, &width, &height);
|
||||
|
||||
if (priv->text_shadow_pipeline == NULL ||
|
||||
width != priv->shadow_width ||
|
||||
height != priv->shadow_height)
|
||||
if (clutter_actor_get_resource_scale (priv->label, &resource_scale))
|
||||
{
|
||||
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
|
||||
ClutterActorBox allocation;
|
||||
float width, height;
|
||||
|
||||
priv->shadow_width = width;
|
||||
priv->shadow_height = height;
|
||||
priv->text_shadow_pipeline = _st_create_shadow_pipeline_from_actor (shadow_spec, priv->label);
|
||||
clutter_actor_get_allocation_box (priv->label, &allocation);
|
||||
clutter_actor_box_get_size (&allocation, &width, &height);
|
||||
|
||||
width *= resource_scale;
|
||||
height *= resource_scale;
|
||||
|
||||
if (priv->text_shadow_pipeline == NULL ||
|
||||
width != priv->shadow_width ||
|
||||
height != priv->shadow_height)
|
||||
{
|
||||
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
|
||||
|
||||
priv->shadow_width = width;
|
||||
priv->shadow_height = height;
|
||||
priv->text_shadow_pipeline =
|
||||
_st_create_shadow_pipeline_from_actor (shadow_spec,
|
||||
priv->label);
|
||||
}
|
||||
|
||||
if (priv->text_shadow_pipeline != NULL)
|
||||
_st_paint_shadow_with_opacity (shadow_spec,
|
||||
cogl_get_draw_framebuffer (),
|
||||
priv->text_shadow_pipeline,
|
||||
&allocation,
|
||||
clutter_actor_get_paint_opacity (priv->label));
|
||||
}
|
||||
|
||||
if (priv->text_shadow_pipeline != NULL)
|
||||
_st_paint_shadow_with_opacity (shadow_spec,
|
||||
cogl_get_draw_framebuffer (),
|
||||
priv->text_shadow_pipeline,
|
||||
&allocation,
|
||||
clutter_actor_get_paint_opacity (priv->label));
|
||||
}
|
||||
|
||||
clutter_actor_paint (priv->label);
|
||||
}
|
||||
|
||||
static void
|
||||
st_label_resource_scale_changed (StWidget *widget)
|
||||
{
|
||||
StLabelPrivate *priv = ST_LABEL (widget)->priv;
|
||||
|
||||
g_clear_pointer (&priv->text_shadow_pipeline, cogl_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
st_label_class_init (StLabelClass *klass)
|
||||
{
|
||||
@@ -243,6 +261,7 @@ st_label_class_init (StLabelClass *klass)
|
||||
actor_class->get_preferred_height = st_label_get_preferred_height;
|
||||
|
||||
widget_class->style_changed = st_label_style_changed;
|
||||
widget_class->resource_scale_changed = st_label_resource_scale_changed;
|
||||
widget_class->get_accessible_type = st_label_accessible_get_type;
|
||||
|
||||
pspec = g_param_spec_object ("clutter-text",
|
||||
|
@@ -359,7 +359,8 @@ blur_pixels (guchar *pixels_in,
|
||||
|
||||
CoglPipeline *
|
||||
_st_create_shadow_pipeline (StShadow *shadow_spec,
|
||||
CoglTexture *src_texture)
|
||||
CoglTexture *src_texture,
|
||||
float resource_scale)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
|
||||
@@ -386,7 +387,7 @@ _st_create_shadow_pipeline (StShadow *shadow_spec,
|
||||
rowstride_in, pixels_in);
|
||||
|
||||
pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
|
||||
shadow_spec->blur,
|
||||
shadow_spec->blur * resource_scale,
|
||||
&width_out, &height_out, &rowstride_out);
|
||||
g_free (pixels_in);
|
||||
|
||||
@@ -431,6 +432,7 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
{
|
||||
ClutterContent *image = NULL;
|
||||
CoglPipeline *shadow_pipeline = NULL;
|
||||
float resource_scale;
|
||||
float width, height;
|
||||
|
||||
g_return_val_if_fail (clutter_actor_has_allocation (actor), NULL);
|
||||
@@ -440,6 +442,12 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
if (width == 0 || height == 0)
|
||||
return NULL;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (actor, &resource_scale))
|
||||
return NULL;
|
||||
|
||||
width = ceilf (width * resource_scale);
|
||||
height = ceilf (height * resource_scale);
|
||||
|
||||
image = clutter_actor_get_content (actor);
|
||||
if (image && CLUTTER_IS_IMAGE (image))
|
||||
{
|
||||
@@ -449,7 +457,8 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
if (texture &&
|
||||
cogl_texture_get_width (texture) == width &&
|
||||
cogl_texture_get_height (texture) == height)
|
||||
shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, texture);
|
||||
shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, texture,
|
||||
resource_scale);
|
||||
}
|
||||
|
||||
if (shadow_pipeline == NULL)
|
||||
@@ -491,6 +500,7 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
|
||||
cogl_framebuffer_translate (fb, -x, -y, 0);
|
||||
cogl_framebuffer_orthographic (fb, 0, 0, width, height, 0, 1.0);
|
||||
cogl_framebuffer_scale (fb, resource_scale, resource_scale, 1);
|
||||
|
||||
clutter_actor_set_opacity_override (actor, 255);
|
||||
clutter_actor_paint (actor);
|
||||
@@ -502,7 +512,8 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
|
||||
cogl_object_unref (fb);
|
||||
|
||||
shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, buffer);
|
||||
shadow_pipeline = _st_create_shadow_pipeline (shadow_spec, buffer,
|
||||
resource_scale);
|
||||
|
||||
cogl_object_unref (buffer);
|
||||
}
|
||||
@@ -528,9 +539,10 @@ _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
* the offset.
|
||||
*/
|
||||
cairo_pattern_t *
|
||||
_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
_st_create_shadow_cairo_pattern (StShadow *shadow_spec_in,
|
||||
cairo_pattern_t *src_pattern)
|
||||
{
|
||||
g_autoptr(StShadow) shadow_spec = NULL;
|
||||
static cairo_user_data_key_t shadow_pattern_user_data;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *src_surface;
|
||||
@@ -541,9 +553,10 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
gint width_in, height_in, rowstride_in;
|
||||
gint width_out, height_out, rowstride_out;
|
||||
cairo_matrix_t shadow_matrix;
|
||||
double xscale_in, yscale_in;
|
||||
int i, j;
|
||||
|
||||
g_return_val_if_fail (shadow_spec != NULL, NULL);
|
||||
g_return_val_if_fail (shadow_spec_in != NULL, NULL);
|
||||
g_return_val_if_fail (src_pattern != NULL, NULL);
|
||||
|
||||
if (cairo_pattern_get_surface (src_pattern, &src_surface) != CAIRO_STATUS_SUCCESS)
|
||||
@@ -556,6 +569,25 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
width_in = cairo_image_surface_get_width (src_surface);
|
||||
height_in = cairo_image_surface_get_height (src_surface);
|
||||
|
||||
cairo_surface_get_device_scale (src_surface, &xscale_in, &yscale_in);
|
||||
|
||||
if (xscale_in != 1.0 || yscale_in != 1.0)
|
||||
{
|
||||
/* Scale the shadow specifications in a temporary copy so that
|
||||
* we can work everywhere in absolute surface coordinates */
|
||||
double scale = (xscale_in + yscale_in) / 2.0;
|
||||
shadow_spec = st_shadow_new (&shadow_spec_in->color,
|
||||
shadow_spec_in->xoffset * xscale_in,
|
||||
shadow_spec_in->yoffset * yscale_in,
|
||||
shadow_spec_in->blur * scale,
|
||||
shadow_spec_in->spread * scale,
|
||||
shadow_spec_in->inset);
|
||||
}
|
||||
else
|
||||
{
|
||||
shadow_spec = st_shadow_ref (shadow_spec_in);
|
||||
}
|
||||
|
||||
/* We want the output to be a color agnostic alpha mask,
|
||||
* so we need to strip the color channels from the input
|
||||
*/
|
||||
@@ -598,6 +630,7 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
width_out,
|
||||
height_out,
|
||||
rowstride_out);
|
||||
cairo_surface_set_device_scale (surface_out, xscale_in, yscale_in);
|
||||
cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data,
|
||||
pixels_out, (cairo_destroy_func_t) g_free);
|
||||
|
||||
@@ -608,6 +641,9 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
|
||||
if (shadow_spec->inset)
|
||||
{
|
||||
/* Scale the matrix in surface absolute coordinates */
|
||||
cairo_matrix_scale (&shadow_matrix, 1.0 / xscale_in, 1.0 / yscale_in);
|
||||
|
||||
/* For inset shadows, offsets and spread radius have already been
|
||||
* applied to the original pattern, so all left to do is shift the
|
||||
* blurred image left, so that it aligns centered under the
|
||||
@@ -616,6 +652,10 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
cairo_matrix_translate (&shadow_matrix,
|
||||
(width_out - width_in) / 2.0,
|
||||
(height_out - height_in) / 2.0);
|
||||
|
||||
/* Scale back the matrix in original coordinates */
|
||||
cairo_matrix_scale (&shadow_matrix, xscale_in, yscale_in);
|
||||
|
||||
cairo_pattern_set_matrix (dst_pattern, &shadow_matrix);
|
||||
return dst_pattern;
|
||||
}
|
||||
@@ -628,6 +668,9 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
/* 6. Invert the matrix back */
|
||||
cairo_matrix_invert (&shadow_matrix);
|
||||
|
||||
/* Scale the matrix in surface absolute coordinates */
|
||||
cairo_matrix_scale (&shadow_matrix, 1.0 / xscale_in, 1.0 / yscale_in);
|
||||
|
||||
/* 5. Adjust based on specified offsets */
|
||||
cairo_matrix_translate (&shadow_matrix,
|
||||
shadow_spec->xoffset,
|
||||
@@ -649,6 +692,9 @@ _st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
- (width_out - width_in) / 2.0,
|
||||
- (height_out - height_in) / 2.0);
|
||||
|
||||
/* Scale back the matrix in scaled coordinates */
|
||||
cairo_matrix_scale (&shadow_matrix, xscale_in, yscale_in);
|
||||
|
||||
/* 1. Invert the matrix so we can work with it in pattern space
|
||||
*/
|
||||
cairo_matrix_invert (&shadow_matrix);
|
||||
|
@@ -63,7 +63,8 @@ CoglPipeline * _st_create_texture_pipeline (CoglTexture *src_texture);
|
||||
|
||||
/* Helper for widgets which need to draw additional shadows */
|
||||
CoglPipeline * _st_create_shadow_pipeline (StShadow *shadow_spec,
|
||||
CoglTexture *src_texture);
|
||||
CoglTexture *src_texture,
|
||||
float resource_scale);
|
||||
CoglPipeline * _st_create_shadow_pipeline_from_actor (StShadow *shadow_spec,
|
||||
ClutterActor *actor);
|
||||
cairo_pattern_t *_st_create_shadow_cairo_pattern (StShadow *shadow_spec,
|
||||
|
@@ -110,8 +110,8 @@ st_scroll_view_fade_paint_target (ClutterOffscreenEffect *effect)
|
||||
*/
|
||||
fade_area_topleft[0] = content_box.x1 + (verts[0].x - paint_box.x1);
|
||||
fade_area_topleft[1] = content_box.y1 + (verts[0].y - paint_box.y1);
|
||||
fade_area_bottomright[0] = content_box.x2 + (verts[3].x - paint_box.x2);
|
||||
fade_area_bottomright[1] = content_box.y2 + (verts[3].y - paint_box.y2);
|
||||
fade_area_bottomright[0] = content_box.x2 + (verts[3].x - paint_box.x2) + 1;
|
||||
fade_area_bottomright[1] = content_box.y2 + (verts[3].y - paint_box.y2) + 1;
|
||||
|
||||
g_object_get (ST_SCROLL_VIEW (self->actor),
|
||||
"hscrollbar-visible", &h_scroll_visible,
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#define KEY_DRAG_THRESHOLD "drag-threshold"
|
||||
#define KEY_GTK_THEME "gtk-theme"
|
||||
#define KEY_GTK_ICON_THEME "icon-theme"
|
||||
#define KEY_MAGNIFIER_ACTIVE "screen-magnifier-enabled"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
@@ -38,6 +39,7 @@ enum {
|
||||
PROP_DRAG_THRESHOLD,
|
||||
PROP_GTK_THEME,
|
||||
PROP_GTK_ICON_THEME,
|
||||
PROP_MAGNIFIER_ACTIVE,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
@@ -48,11 +50,13 @@ struct _StSettings
|
||||
GObject parent_object;
|
||||
GSettings *interface_settings;
|
||||
GSettings *mouse_settings;
|
||||
GSettings *a11y_settings;
|
||||
|
||||
gchar *gtk_theme;
|
||||
gchar *gtk_icon_theme;
|
||||
gboolean enable_animations;
|
||||
gboolean primary_paste;
|
||||
gboolean magnifier_active;
|
||||
gint drag_threshold;
|
||||
};
|
||||
|
||||
@@ -105,6 +109,9 @@ st_settings_get_property (GObject *object,
|
||||
case PROP_GTK_ICON_THEME:
|
||||
g_value_set_string (value, settings->gtk_icon_theme);
|
||||
break;
|
||||
case PROP_MAGNIFIER_ACTIVE:
|
||||
g_value_set_boolean (value, settings->magnifier_active);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -144,6 +151,11 @@ st_settings_class_init (StSettingsClass *klass)
|
||||
"GTK+ Icon Theme",
|
||||
"",
|
||||
G_PARAM_READABLE);
|
||||
props[PROP_MAGNIFIER_ACTIVE] = g_param_spec_boolean("magnifier-active",
|
||||
"Magnifier is active",
|
||||
"Weather the a11y magnifier is active",
|
||||
FALSE,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
}
|
||||
@@ -190,6 +202,18 @@ on_mouse_settings_changed (GSettings *g_settings,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_a11y_settings_changed (GSettings *g_settings,
|
||||
const gchar *key,
|
||||
StSettings *settings)
|
||||
{
|
||||
if (g_str_equal (key, KEY_MAGNIFIER_ACTIVE))
|
||||
{
|
||||
settings->magnifier_active = g_settings_get_boolean (g_settings, key);
|
||||
g_object_notify_by_pspec (G_OBJECT (settings), props[PROP_MAGNIFIER_ACTIVE]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_settings_init (StSettings *settings)
|
||||
{
|
||||
@@ -201,6 +225,10 @@ st_settings_init (StSettings *settings)
|
||||
g_signal_connect (settings->interface_settings, "changed",
|
||||
G_CALLBACK (on_mouse_settings_changed), settings);
|
||||
|
||||
settings->a11y_settings = g_settings_new ("org.gnome.desktop.a11y.applications");
|
||||
g_signal_connect (settings->a11y_settings, "changed",
|
||||
G_CALLBACK (on_a11y_settings_changed), settings);
|
||||
|
||||
settings->enable_animations = g_settings_get_boolean (settings->interface_settings,
|
||||
KEY_ENABLE_ANIMATIONS);
|
||||
settings->primary_paste = g_settings_get_boolean (settings->interface_settings,
|
||||
@@ -211,6 +239,8 @@ st_settings_init (StSettings *settings)
|
||||
KEY_GTK_ICON_THEME);
|
||||
settings->drag_threshold = g_settings_get_int (settings->mouse_settings,
|
||||
KEY_DRAG_THRESHOLD);
|
||||
settings->magnifier_active = g_settings_get_boolean (settings->a11y_settings,
|
||||
KEY_MAGNIFIER_ACTIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user