Compare commits

..

7 Commits

Author SHA1 Message Date
Florian Müllner
ee3cd450a5 build: Don't introspect ShellMenu
It is now only used internally by ShellApp to track remote actions,
so there's no need to expose it to javascript code.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:35:30 +01:00
Florian Müllner
996369a22d build: Remove remote menu support
It is now unused.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:35:30 +01:00
Florian Müllner
ce6ab7e121 app: Remove :menu property
It is now unused.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:34:59 +01:00
Florian Müllner
3da747ec2d app: Don't rely on app menu to check for GtkApplications
As the app menu is being phased out, it is no longer a good indicator
for GtkApplications. Instead, base the check directly on the appropriate
D-Bus properties.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:34:59 +01:00
Florian Müllner
593f15ad63 windowMenu: Remove fallback app menu support
With the app menu being phased out entirely, there's no good reason to
keep support for the fallback app menu in decorations either - the number
of applications that set an app menu and haven't embraced client-side
decorations is extremely small, and they should already have alternative
fallbacks for non-GNOME environment in place.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:34:59 +01:00
Florian Müllner
acdbd28262 panel: Remove the app menu
As the app menu is in the process of being retired[0], stop displaying
it in the shell - GTK+ still has a fallback path for applications that
haven't removed it yet.

[0] https://gitlab.gnome.org/GNOME/Initiatives/wikis/App-Menu-Retirement

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:34:00 +01:00
Florian Müllner
ca70a4fc17 panel: Remove unused import
https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-26 14:32:20 +01:00
436 changed files with 43206 additions and 114102 deletions

View File

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

1
.gitignore vendored
View File

@@ -80,4 +80,3 @@ tests/run-test.sh
*~ *~
*.patch *.patch
*.sw? *.sw?
.vscode

View File

@@ -1,98 +0,0 @@
stages:
- review
- 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.gitlab.gnome.org/gnome/mutter/master:v3
stage: review
variables:
GIT_DEPTH: "100"
script:
- ./.gitlab-ci/check-commit-log.sh
only:
- merge_requests
js_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG)
<<: *only_default
artifacts:
paths:
- ${JS_LOG}
when: on_failure
eslint:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- ./.gitlab-ci/run-eslint.sh
<<: *only_default
artifacts:
paths:
- reports
when: always
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
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 -Dman=false --werror
- ninja -C build
- ninja -C build install
<<: *only_default
artifacts:
expire_in: 1 day
paths:
- mutter
- build
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stage: test
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
NO_AT_BRIDGE: "1"
before_script:
- ninja -C mutter/build install
script:
- dbus-run-session -- 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/mutter/master:v3
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

View File

@@ -1,18 +0,0 @@
FROM registry.fedoraproject.org/fedora:latest
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' git && \
# 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

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env bash
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
echo Cannot review non-merge request
exit 1
fi
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
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
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

View File

@@ -1,33 +0,0 @@
#!/usr/bin/bash
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 -q $merge_request_remote $merge_request_branch 2>/dev/null; then
mutter_target=FETCH_HEAD
else
mutter_target=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
echo Using $mutter_target instead
fi
fi
if [ -z "$mutter_target" ]; then
mutter_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
mutter_target=${mutter_target:-origin/master}
echo Using $mutter_target instead
fi
git checkout -q $mutter_target

View File

@@ -1,114 +0,0 @@
#!/usr/bin/env bash
OUTPUT_REGULAR=reports/lint-regular-report.txt
OUTPUT_LEGACY=reports/lint-legacy-report.txt
OUTPUT_FINAL=reports/lint-common-report.txt
OUTPUT_MR=reports/lint-mr-report.txt
LINE_CHANGES=changed-lines.txt
is_empty() {
(! grep -q . $1)
}
run_eslint() {
ARGS_LEGACY='--config lint/eslintrc-legacy.yml'
local extra_args=ARGS_$1
local output_var=OUTPUT_$1
local output=${!output_var}
# ensure output exists even if eslint doesn't report any errors
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js
}
list_commit_range_additions() {
# Turn raw context-less git-diff into a list of
# filename:lineno pairs of new (+) lines
git diff -U0 "$@" -- js |
awk '
BEGIN { file=""; }
/^+++ b/ { file=substr($0,7); }
/^@@ / {
len = split($3,a,",")
start=a[1]
count=(len > 1) ? a[2] : 1
for (line=start; line<start+count; line++)
printf "%s/%s:%d:\n",ENVIRON["PWD"],file,line;
}'
}
copy_matched_lines() {
local source=$1
local matches=$2
local target=$3
echo -n > $target
for l in $(<$matches); do
grep $l $source >> $target
done
}
create_common() {
# comm requires sorted input;
# we also strip the error message to make the following a "common" error:
# regular:
# file.js:42:23 Indentation of 55, expected 42
# legacy:
# file.js:42:23 Indentation of 55, extected 24
prepare() {
sed 's: .*::' $1 | sort
}
comm -12 <(prepare $OUTPUT_REGULAR) <(prepare $OUTPUT_LEGACY) >$OUTPUT_FINAL.tmp
# Now add back the stripped error messages
copy_matched_lines $OUTPUT_REGULAR $OUTPUT_FINAL.tmp $OUTPUT_FINAL
rm $OUTPUT_FINAL.tmp
}
# Disable MR handling for now. We aren't ready to enforce
# non-legacy style just yet ...
unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME
REMOTE=${1:-$CI_MERGE_REQUEST_PROJECT_URL.git}
BRANCH_NAME=${2:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
if [ "$BRANCH_NAME" ]; then
git fetch $REMOTE $BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commit_range=$branch_point...HEAD
list_commit_range_additions $commit_range > $LINE_CHANGES
# Don't bother with running lint when no JS changed
if is_empty $LINE_CHANGES; then
exit 0
fi
fi
echo Generating lint report using regular configuration
run_eslint REGULAR
echo Generating lint report using legacy configuration
run_eslint LEGACY
echo Done.
create_common
if ! is_empty $OUTPUT_FINAL; then
cat $OUTPUT_FINAL
exit 1
fi
# Just show the report and succeed when not testing a MR
if [ -z "$BRANCH_NAME" ]; then
exit 0
fi
copy_matched_lines $OUTPUT_REGULAR $LINE_CHANGES $OUTPUT_MR
cat $OUTPUT_MR
is_empty $OUTPUT_MR

31
.project Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gnome-shell</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.linuxtools.cdt.autotools.genmakebuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.eclipse.linuxtools.cdt.autotools.autotoolsNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,148 @@
#Fri Nov 28 14:33:30 EST 2008
eclipse.preferences.version=1
org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=80
org.eclipse.cdt.core.formatter.alignment_for_compact_if=0
org.eclipse.cdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.cdt.core.formatter.alignment_for_declarator_list=16
org.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48
org.eclipse.cdt.core.formatter.alignment_for_expression_list=0
org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.cdt.core.formatter.brace_position_for_array_initializer=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_block=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_block_in_case=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line
org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=next_line
org.eclipse.cdt.core.formatter.brace_position_for_switch=next_line_shifted
org.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line
org.eclipse.cdt.core.formatter.compact_else_if=true
org.eclipse.cdt.core.formatter.continuation_indentation=2
org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true
org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=true
org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=true
org.eclipse.cdt.core.formatter.indent_empty_lines=false
org.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.cdt.core.formatter.indentation.size=8
org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=insert
org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=insert
org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert
org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.cdt.core.formatter.lineSplit=80
org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.cdt.core.formatter.tabulation.char=space
org.eclipse.cdt.core.formatter.tabulation.size=2
org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false

View File

@@ -0,0 +1,4 @@
#Fri Nov 28 14:33:30 EST 2008
eclipse.preferences.version=1
formatter_profile=org.eclipse.cdt.ui.default.gnu_profile
formatter_settings_version=1

View File

@@ -0,0 +1,315 @@
#Fri Nov 28 14:43:43 EST 2008
eclipse.preferences.version=1
org.eclipse.wst.jsdt.core.codeComplete.argumentPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.argumentSuffixes=
org.eclipse.wst.jsdt.core.codeComplete.fieldPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.fieldSuffixes=
org.eclipse.wst.jsdt.core.codeComplete.localPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.localSuffixes=
org.eclipse.wst.jsdt.core.codeComplete.staticFieldPrefixes=
org.eclipse.wst.jsdt.core.codeComplete.staticFieldSuffixes=
org.eclipse.wst.jsdt.core.compiler.codegen.inlineJsrBytecode=disabled
org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.wst.jsdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.wst.jsdt.core.compiler.compliance=1.4
org.eclipse.wst.jsdt.core.compiler.debug.lineNumber=generate
org.eclipse.wst.jsdt.core.compiler.debug.localVariable=generate
org.eclipse.wst.jsdt.core.compiler.debug.sourceFile=generate
org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier=warning
org.eclipse.wst.jsdt.core.compiler.problem.deprecation=warning
org.eclipse.wst.jsdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.wst.jsdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.wst.jsdt.core.compiler.problem.discouragedReference=warning
org.eclipse.wst.jsdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.wst.jsdt.core.compiler.problem.enumIdentifier=warning
org.eclipse.wst.jsdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.wst.jsdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.wst.jsdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.wst.jsdt.core.compiler.problem.forbiddenReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.wst.jsdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.wst.jsdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.wst.jsdt.core.compiler.problem.looseVarDecleration=warning
org.eclipse.wst.jsdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.wst.jsdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.wst.jsdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.wst.jsdt.core.compiler.problem.nullReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.optionalSemicolon=warning
org.eclipse.wst.jsdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.wst.jsdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.wst.jsdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.wst.jsdt.core.compiler.problem.undefinedField=warning
org.eclipse.wst.jsdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedFieldReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedMethodReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unresolvedTypeReference=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.wst.jsdt.core.compiler.problem.unusedLabel=warning
org.eclipse.wst.jsdt.core.compiler.problem.unusedLocal=warning
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.wst.jsdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.wst.jsdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.wst.jsdt.core.compiler.source=1.3
org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns=false
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment=0
org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field=0
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package=0
org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations=0
org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments=true
org.eclipse.wst.jsdt.core.formatter.comment.format_header=false
org.eclipse.wst.jsdt.core.formatter.comment.format_html=true
org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments=true
org.eclipse.wst.jsdt.core.formatter.comment.format_source_code=true
org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags=true
org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags=insert
org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter=insert
org.eclipse.wst.jsdt.core.formatter.comment.line_length=80
org.eclipse.wst.jsdt.core.formatter.compact_else_if=true
org.eclipse.wst.jsdt.core.formatter.continuation_indentation=2
org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer=1
org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.wst.jsdt.core.formatter.indent_empty_lines=false
org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.wst.jsdt.core.formatter.indentation.size=4
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.wst.jsdt.core.formatter.lineSplit=80
org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.wst.jsdt.core.formatter.tabulation.char=space
org.eclipse.wst.jsdt.core.formatter.tabulation.size=4
org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator=true

View File

@@ -0,0 +1,10 @@
#Fri Nov 28 14:39:12 EST 2008
eclipse.preferences.version=1
formatter_profile=_gjs
formatter_settings_version=11
org.eclipse.wst.jsdt.ui.exception.name=e
org.eclipse.wst.jsdt.ui.gettersetter.use.is=true
org.eclipse.wst.jsdt.ui.javadoc=false
org.eclipse.wst.jsdt.ui.keywordthis=false
org.eclipse.wst.jsdt.ui.overrideannotation=true
org.eclipse.wst.jsdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>

View File

@@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@@ -0,0 +1 @@
Window

View File

@@ -80,10 +80,13 @@ e.g. `imports.ui.popupMenu`.
Each import block should be sorted alphabetically. Don't import modules you Each import block should be sorted alphabetically. Don't import modules you
don't use. don't use.
```javascript ```javascript
const { GLib, Gio, St } = imports.gi; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util; const Util = imports.misc.util;
``` ```
The alphabetical ordering should be done independently of the location of the The alphabetical ordering should be done independently of the location of the
@@ -155,24 +158,18 @@ you to inherit from a type to use it, you can do so:
var MyClutterActor = GObject.registerClass( var MyClutterActor = GObject.registerClass(
class MyClutterActor extends Clutter.Actor { class MyClutterActor extends Clutter.Actor {
vfunc_get_preferred_width(forHeight) { vfunc_get_preferred_width(actor, forHeight) {
return [100, 100]; return [100, 100];
} }
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(actor, forWidth) {
return [100, 100]; return [100, 100];
} }
vfunc_paint(paintContext) { vfunc_paint(actor) {
let framebuffer = paintContext.get_framebuffer();
let coglContext = framebuffer.get_context();
let alloc = this.get_allocation_box(); let alloc = this.get_allocation_box();
Cogl.set_source_color4ub(255, 0, 0, 255);
let pipeline = new Cogl.Pipeline(coglContext); Cogl.rectangle(alloc.x1, alloc.y1,
pipeline.set_color4ub(255, 0, 0, 255);
framebuffer.draw_rectangle(pipeline,
alloc.x1, alloc.y1,
alloc.x2, alloc.y2); alloc.x2, alloc.y2);
} }
}); });
@@ -192,27 +189,15 @@ and "double quotes" for strings that the user may see. This allows us to
quickly find untranslated or mistranslated strings by grepping through the quickly find untranslated or mistranslated strings by grepping through the
sources for double quotes without a gettext call around them. sources for double quotes without a gettext call around them.
## `actor` (deprecated) and `_delegate` ## `actor` and `_delegate`
gjs allows us to set so-called "expando properties" on introspected objects, gjs allows us to set so-called "expando properties" on introspected objects,
allowing us to treat them like any other. Because the Shell was built before allowing us to treat them like any other. Because the Shell was built before
you could inherit from GTypes natively in JS, in some cases we have a wrapper you could inherit from GTypes natively in JS, we usually have a wrapper class
class that has a property called `actor` (now deprecated). We call this that has a property called `actor`. We call this wrapper class the "delegate".
wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on We sometimes use expando properties to set a property called `_delegate` on
the actor itself: the actor itself:
```javascript
var MyActor = GObject.registerClass(
class MyActor extends Clutter.Actor {
_init(params) {
super._init(params);
this._delegate = this;
}
});
```
Or using the deprecated `actor`:
```javascript ```javascript
var MyClass = class { var MyClass = class {
constructor() { constructor() {
@@ -233,7 +218,6 @@ delegate object from an associated actor. For instance, the drag and drop
system calls the `handleDragOver` function on the delegate of a "drop target" system calls the `handleDragOver` function on the delegate of a "drop target"
when the user drags an item over it. If you do not set the `_delegate` when the user drags an item over it. If you do not set the `_delegate`
property, your actor will not be able to be dropped onto. property, your actor will not be able to be dropped onto.
In case the class is an actor itself, the `_delegate` can be just set to `this`.
## Functional style ## Functional style
@@ -295,49 +279,34 @@ If your usage of an object is like a hash table (and thus conceptually the keys
can have special chars in them), don't use quotes, but use brackets: `{ bar: 42 can have special chars in them), don't use quotes, but use brackets: `{ bar: 42
}`, `foo['bar']`. }`, `foo['bar']`.
## Animations ## Getters, setters, and Tweener
Most objects that are animated are actors, and most properties used in animations
are animatable, which means they can use implicit animations:
Getters and setters should be used when you are dealing with an API that is
designed around setting properties, like Tweener. If you want to animate an
arbitrary property, create a getter and setter, and use Tweener to animate the
property.
```javascript ```javascript
moveActor(actor, x, y) { var ANIMATION_TIME = 2000;
actor.ease({
x, var MyClass = class {
y, constructor() {
duration: 500, // ms this.actor = new St.BoxLayout();
mode: Clutter.AnimationMode.EASE_OUT_QUAD this._position = 0;
});
} }
```
The above is a convenience wrapper around the actual Clutter API, and should generally get position() {
be preferred over the more verbose: return this._position;
```javascript
moveActor(actor, x, y) {
actor.save_easing_state();
actor.set_easing_duration(500);
actor.set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
actor.set({
x,
y
});
actor.restore_easing_state();
} }
```
There is a similar convenience API around Clutter.PropertyTransition to animate set position(value) {
actor (or actor meta) properties that cannot use implicit animations: this._position = value;
this.actor.set_position(value, value);
```javascript
desaturateActor(actor, desaturate) {
let factor = desaturate ? 1.0 : 0.0;
actor.ease_property('@effects.desaturate.factor', factor, {
duration: 500, // ms
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
} }
};
let myThing = new MyClass();
Tweener.addTween(myThing,
{ position: 100,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
``` ```

415
NEWS
View File

@@ -1,418 +1,3 @@
3.35.2
======
* Fix unredirection after cancelled animations [Florian; #1788]
* Include shadow in window screenshots [Robert; !762]
* Show indicator when microphone is active [Florian; !729]
* Use inheritance instead of delegate pattern [Marco; !559]
* Use cached coordinates for window sorting in overview [Andrew; !763]
* Wiggle login/unlock password entries on failure [Georges; !769]
* Update window titles in app menu [Florian; #1830]
* Fix window animations getting stuck by workspace switches [Jonas D.; !784]
* Fix not-responding dialog size when using geometry scaling [Jonas D.; !783]
* Handle buggy MPRIS clients more gracefully [Philip; #1362]
* Deprecate StBoxLayout's child properties [Florian; !780]
* Remove StBin's align properties [Florian; !803]
* Use correct timezones for events [Milan, Florian; !806, #1895]
* Reduce overhead of tracking stylesheet changes [Carlos; !779]
* Replace action icons in system menu with regular menu items [Florian; #270]
* Refine polkit dialogs [Jonas D.; !788]
* Fix battery icon glitch in "100% but charging" case [Philip; !814]
* Fix windows getting stuck on screen if closed while animating [Florian; !815]
* Use font from interface settings [Florian; #688288]
* Show polkit confirmation dialog for users with no password
[Joaquim, Jonas D.; !829]
* Use better OSK layout fallback for unsupported variants [Florian; #1907]
* Hide stopped spinner in top bar [Joonas; !832]
* Reuse existing icons when updating the app picker grid [Georges; !841]
* Show switcher popups immediately on second key press [Florian; #1928]
* Add position-based animation to page indicators [Alexander; !843]
* Improve modifier-less keyboard navigation of switcher popups [Florian; #1883]
* Improve weather integration [Florian; #1927, #1926]
* Add back sound feedback when scrolling volume indicator [Florian; #53]
* Fix creating app folders with no pre-existing folders [Jonas D.; #1652]
* Improve DND page switching in app picker [Florian, Jonas D.; #1693]
* Fix disable command of gnome-extensions tool [Florian; #1946]
* Tweak styling of notifications/media constrols [Joonas; !855, !865]
* Enable clean session shutdown after gnome-shell failure [Benjamin; !858]
* Also remove scaled keys when texture cache is cleared [Daniel M.; !567]
* Don't show overflow indicator in switchers that fit screen [Florian; #1834]
* Move libcroco dependency in-tree [Federico; !861]
* Move to app folder location when it is created/renamed [Georges; !883]
* Dismiss switcher popups when a system modal dialogs opens [Florian; #1536]
* Fix weather forecasts for automatic location when Weather is not sandboxed
[Florian; #1823]
* Place launched applications into a systemd scope [Benjamin; !863]
* Fixed crashes [Jonas D., Carlos; !787, !813]
* Misc. bug fixes and cleanups [Marco, Georges, Daniel V., Florian, Robert,
Kalev, Philip, Jonas D., Will, Carlos, Jonas Å., cunidev, Joonas, Federico;
!747, !765, !421, !759, !749, !730, !770, #1799, !774, !773, !776, !777,
!782, !794, !778, !792, !790, !190, !796, !795, !797, !798, !800, !804, !808,
!807, !810, !811, !563, !809, !805, !817, !818, !822, !830, !828, !823, !835,
!840, !842, !833, !845, !846, !847, !851, #1916, !862, !866, #1979, !827,
#1976, !884, !873, !885, !799, !887, !891, !816]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Philip Chimento, Milan Crha,
Jonas Dreßler, Carlos Garnacho, Joonas Henriksson, Kalev Lember, Robert Mader,
Alexander Mikhaylenko, Daniel García Moreno, Florian Müllner,
Georges Basile Stavracas Neto, Federico Mena Quintero, Joaquim Rocha,
Will Thompson, Daniel van Vugt, Andrew Watson, cunidev, Jonas Ådahl
Translators:
Daniel Mustieles [es], Goran Vidović [hr], Fabio Tomat [fur],
Danial Behzadi [fa], Andika Triwidada [id], Efstathios Iosifidis [el],
Ricardo Silva Veloso [pt_BR]
3.35.1
======
* Misc. bug fixes and cleanups [Marco; Matthias; !758, #701212]
Contributors:
Marco Trevisan (Treviño)
3.34.1
======
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]
* Allow editing app folder names [Georges, Marco; !675, !720]
* Skip property transitions while hidden [Florian; !708]
* Make menu animations more consistent [Florian, GB_2; #1595, !717]
* Improve performance when enabling/disabling all extensions [Jonas D.; !96]
* Fix extra icons appearing in "Frequent" view animation [Georges; !696]
* Fix fading out desktop icons [Harshula; #1616]
* Fix box-shadow glitch with prerendered resources [Daniel; #1186]
* Fix accidentally skipped animations [Florian; #1572]
* Fix screenshots and window animations when scaled [Robert; !728]
* Don't leak NOTIFY_SOCKET environment variable to applications [Benjamin; !741]
* Fix lock-up on X11 when ibus is already running on startup [Marco; #1712]
* Fix screen dimming on idle [Marco; #1683]
* Do not notify systemd before initialization is complete [Iain; !750]
* Support SAE secrets in network agent [Lubomir; !751]
* Fix various regressions with dynamic workspaces [Florian; #1497]
* Fixed crashes [Florian, Marco; #1678, !746]
* Misc. bug fixes and cleanups [Marco, Jonas D., Florian, Iain, Georges,
Jonas Å., Martin, Takao, Carlos; !700, !705, !709, !711, !707, #1538, !710,
!713, !699, !715, !718, !716, !719, !721, #1243, !725, !731, #1614, !683,
!732, !121, !735, !736, !740, #573, #1641, #1571]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Jonas Dreßler, Takao Fujiwara, GB_2,
Carlos Garnacho, Harshula Jayasuriya, Iain Lane, Robert Mader,
Daniel García Moreno, Florian Müllner, Georges Basile Stavracas Neto,
Lubomir Rintel, Martin Zurowietz, Jonas Ådahl
Translators:
Rafael Fontenelle [pt_BR], Fran Dieguez [gl], Balázs Úr [hu],
Milo Casagrande [it], Daniel Șerbănescu [ro], Kukuh Syafaat [id],
Jiri Grönroos [fi], Daniel Mustieles [es], Piotr Drąg [pl],
Anders Jonsson [sv], Marek Černocký [cs], Jordi Mas [ca],
Aurimas Černius [lt], Christian Kirbach [de], Emin Tufan Çetin [tr],
Enrico Nicoletto [pt_BR], Danial Behzadi [fa], Марко Костић [sr],
Alexandre Franke [fr], Charles Monzat [fr], Kjartan Maraas [nb],
Ryuta Fujii [ja], Nathan Follens [nl], Dušan Kazik [sk], Fabio Tomat [fur],
Matej Urbančič [sl], Ask Hjorth Larsen [da], Alan Mortensen [da]
3.34.0
======
* Handle startup/shutdown of misc X11 services [Carlos; !680]
* Fix sound volume mute/unmute [Iain; #1557]
* Correctly terminate pasted text [Carlos; #1570]
Contributors:
Carlos Garnacho, Iain Lane
Translators:
Tom Tryfonidis [el], Milo Casagrande [it], Ryuta Fujii [ja],
Efstathios Iosifidis [el], Carmen Bianca BAKKER [eo], Sabri Ünal [tr],
Dušan Kazik [sk], Balázs Meskó [hu], Claude Paroz [fr]
3.33.92
=======
* Animate pointer a11y pie timer [Jonas D.; !688]
* Fix restarting shell in systemd user session [Benjamin; !690]
* Misc. bug fixes and cleanups [Florian, Jonas D., Jonas Å., Will;
!691, !689, !692, #1552, !698]
Contributors:
Jonas Ådahl, Benjamin Berg, Piotr Drąg, Jonas Dreßler, Florian Müllner,
Will Thompson
Translators:
Daniel Șerbănescu [ro], Danial Behzadi [fa], Daniel Mustieles [es],
Jiri Grönroos [fi], Asier Sarasua Garmendia [eu], Piotr Drąg [pl],
Rūdolfs Mazurs [lv], Anders Jonsson [sv], Fran Dieguez [gl], Jordi Mas [ca],
Matej Urbančič [sl], Zander Brown [en_GB], Ryuta Fujii [ja], Tim Sabsch [de],
Fabio Tomat [fur], Pawan Chitrakar [ne], A S Alam [pa], Changwoo Ryu [ko],
Aurimas Černius [lt], Daniel Rusek [cs], Marek Černocký [cs],
Kukuh Syafaat [id], Goran Vidović [hr], Rafael Fontenelle [pt_BR]
3.33.91
=======
* Fix regression when adjusting brightness [Florian; #1500]
* Fix pointer a11y timeout animation [Jonas D.; #1533]
* Add new extensions CLI tool [Florian; #1234]
* Only track top-level windows [Carlos; #556]
* Misc. bug fixes and cleanups [Jonas D., Jonas Å., Piotr, Florian;
!678, !682, !686]
Contributors:
Jonas Ådahl, Jonas Dreßler, Carlos Garnacho, Florian Müllner
Translators:
Asier Sarasua Garmendia [eu], Sveinn í Felli [is], Anders Jonsson [sv],
Jordi Mas [ca], Kukuh Syafaat [id], Florentina Mușat [ro], Jiri Grönroos [fi],
Aurimas Černius [lt], Daniel Mustieles [es], Piotr Drąg [pl],
Danial Behzadi [fa]
3.33.90
=======
* Implement DND app picker folder management [Georges; !643, !645, !664, !671]
* Make Clocks/Weather integration work with sandboxed apps [Florian; #1158]
* Support startup via systemd user instance [Benjamin; !507]
* Replace Tweener with Clutter animations [Florian; !663, !22, !666, !668, !669]
* Minimize travel distance in overview animation [Sergey; !267]
* Rescan icon theme when installed apps changed [Georges; !661]
* Consistently animate new window actions [Jonas; !662, !673]
* Misc. bug fixes and cleanups [Florian, Daniel, Ray, Bastien, Jonas, Niels,
Marco, Georges; !635, !636, !637, #1462, !628, !640, !641, !627, !644, !647,
!385, #1474, !651, #1144, !646, !653, !652, !655, #1482, !656, $654, !665,
!667, !670, #1357, !672, !657, #1507, !674, !677]
Contributors:
Benjamin Berg, Sergey Bugaev, Jonas Dreßler, Niels De Graef, Florian Müllner,
Georges Basile Stavracas Neto, Bastien Nocera, Ray Strode,
Marco Trevisan (Treviño), verdre, Daniel van Vugt
Translators:
Asier Sarasua Garmendia [eu], Rafael Fontenelle [pt_BR],
Kristjan SCHMIDT [eo], Jor Teron [mjw], Daniel Mustieles [es],
Kukuh Syafaat [id], Jordi Mas [ca], Fabio Tomat [fur], Daniel Șerbănescu [ro],
Anders Jonsson [sv]
3.33.4
======
* Fix unintentional interference between gestures [Jonas; !598]
* Fix unintentional loop while polkit dialog is active [Ray; !602]
* Fix alt-tab icon size on HiDPI [Jonas; !587]
* Style fixes and improvements [Frederik, Jakub; !610, #1446, #1449]
* Fix style updates for non-background CSS properties [Florian; #1212]
* Fix cursor visibility in screen recordings [Illya; #1208]
* Add option for disabling the hot corner [Florian; #688320]
* Use more fine-grained levels in battery indicator [Florian; !561, #1442]
* Fix the calculation of the maximum number of app search results [Jonas; !110]
* Handle horizontal workspace layout with gestures/animations [Florian; !575]
* Improve handling of session mode extensions [Florian, Didier; #789852]
* Misc. bug fixes and cleanups [Jonas, Florian, Sonny, Carlos, Mario, Benjamin,
Marco, Ting-Wei; !599, !600, !591, !606, !152, !607, !604, !495, !608, !611,
!614, !612, !615, !618, #369, !620, #774, !621, !616, #1065, !609, !626,
!491, !631, !632, !633, #1457]
Contributors:
Benjamin Berg, Jonas Dreßler, Frederik Feichtmeier, Carlos Garnacho,
Illya Klymov, Ting-Wei Lan, Florian Müllner, Sonny Piers, Mario Sanchez Prada,
Didier Roche, Jakub Steiner, Ray Strode, Jor Teron, Marco Trevisan (Treviño)
Translators:
Jordi Mas [ca], Jor Teron [mjw]
3.33.3
======
* Prepare for optional X11 [Carlos; !378]
* Fix opening window menu [Marco; !557]
* Reload search providers when installed applications change [Cosimo; !562]
* Implement locate-pointer accessibility feature [Olivier; #981]
* Allow to disable window menus via session mode [Cosimo; !569]
* Implement mouse accessibility [Olivier; !474]
* Call GDM's RegisterSession() after startup [Iain; !570]
* Fix extended keys popups being hidden by on-screen keyboard [Marco; !583]
* Fix top bar being hidden by lock screen [Jonas; !571]
* Update theme to better match GTK's Adwaita [Frederik; #841]
* Set up GJS profiler when GJS_TRACE_FD is set [Christian; !573]
* Misc. bug fixes and cleanups [Jonas, Cosimo, Robert, Florian, Marco, Simon,
Laurent, Niels, Will; !551, !555, !464, #1333, !565, !572, !568, !558, #1205,
#1336, !579, !576, #1392, !582, !586, #1406, #1351]
Contributors:
Laurent Bigonville, Cosimo Cecchi, Piotr Drąg, Jonas Dreßler,
Frederik Feichtmeier, Olivier Fourdan, Carlos Garnacho, Niels De Graef,
Christian Hergert, Iain Lane, Robert Mader, Florian Müllner, Simon Schampijer,
Jakub Steiner, Will Thompson, Marco Trevisan (Treviño)
Translators:
Kukuh Syafaat [id], Balázs Meskó [hu], Daniel Mustieles [es],
Fabio Tomat [fur], Nathan Follens [nl], Goran Vidović [hr], Jordi Mas [ca]
3.33.2
======
* Fix keeping actors visible in scrollviews [Marco; #1061]
* Move some chrome above popup windows [Jonas D.; !358]
* Include 'sandboxed-app-id' in winodw introspection info [Florian; #1289]
* Port to libecal-2.0 [Milan; !501]
* Support TCRYPT in mount password dialog [segfault; !126]
* Misc. bug fixes and cleanups [Florian, Marco, Veerasamy; !517, #745, !499,
!510, !515, !546, !549]
Contributors:
Cosimo Cecchi, Milan Crha, Jonas Dreßler, Florian Müllner, segfault,
Veerasamy Sevagen, Marco Trevisan (Treviño)
Translators:
Daniel Mustieles [es]
3.33.1
======
* Refine the app menu [Florian; #968]
* Refine window preview style [Feichtmeier; !461]
* Only emit ::style-changed on actual changes [Carlos; #1153]
* Disable emoji on-screen keyboard support on X11 [Florian; #1172]
* Fix tablet button mapping overlay [Carlos; #1220]
* Don't crash for world clock locations with no timezone [Florian; #1062]
* Don't leak old on-screen keyboard layout groups [Carlos; mutter#556]
* Fix ellipsization in dialog subtitles/bodies [Marco; !531]
* Fix glitch of fullscreen window in workspace switch animation [Jonas D.; !322]
* Fix distortion of some image contents [Florian; !525]
* Allow dragging unfocused tiled/maximized windows from top bar [Dylan; #679290]
* Handle network interface name changes [Fabrice; !534]
* Avoid unnecessary style changes when computing :first/:last-child
[Florian; !529]
* Misc. bug fixes and cleanups [Florian, Marco, Robert, Georges, Carlos, Simon,
Jonas D.; !487, !441, !502, !503, !504, !506, #822, !551, !512, !509, !511,
#1054, !524, #1065, !331, !540]
Contributors:
Fabrice Bellet, Jonas Dreßler, Feichtmeier, Carlos Garnacho, Robert Mader,
Dylan McCall, Simon McVittie, Florian Müllner, Georges Basile Stavracas Neto,
Marco Trevisan (Treviño)
Translators:
Daniel Mustieles [es], Kukuh Syafaat [id], Fabio Tomat [fur],
Carmen Bianca BAKKER [eo], Dingzhong Chen [zh_CN], Tim Sabsch [de]
3.32.1
======
* Fix avatar scaling on login screen [Florian; #1024]
* Fix distortion of desktop zoom [Florian; #646]
* Fix mouse cursor visibility when using desktop zoom [Florian, Marco; #1020]
* Fix screen dimming after wake-up on lock screen [Xiaoguang; #900]
* Fix Alt+Esc switcher [Florian; #1064]
* Respect struts for popover placement [Andrea; #1102]
* Fix app icons updates after theme changes [Florian; #1117]
* Fix desktop zoom after resolution changes [Marco; #1120]
* Implement stick-to-finger workspace switch overview gestures [Florian; #516]
* Make World Clocks offsets relative to local time [Florian; #1157]
* Fix top app icon disappearing from dash [Florian; #1053]
* Update switch style to match new Adwaita [Jakub; !496]
* Ensure CSS units are pixel-aligned when scaling is used [Carlos; #91]
* Misc. bug fixes and cleanups [Florian, Jakub, Robert, Alex, Carlos, Phil,
Marco, Benjamin, AsciiWolf, Ray, verdre; !444, #1016, #1018, !449, #1036,
!455, #1094, !440, #1023, #624, #1017, !476, !473, !480, #1130, !485, !481,
!490, !489, #1151, !435, #1160, !482, #1150, #1166, !384]
Contributors:
AsciiWolf, Andrea Azzarone, Benjamin Berg, Carlos Garnacho, Victor Ibragimov,
Robert Mader, Alex Monday, Florian Müllner, Jakub Steiner, Ray Strode,
Marco Trevisan (Treviño), verdre, Xiaoguang Wang, Phil Wyett
Translators:
Victor Ibragimov [tg, af, et, ja], Bruce Cowan [en_GB], Piotr Drąg [tg],
Charles Monzat [fr], Khaled Hosny [ar], Goran Vidović [hr],
Cheng-Chia Tseng [zh_TW], Carmen Bianca BAKKER [eo], Daniel Mustieles [es],
Dušan Kazik [sk]
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]
* Don't let unfullscreen gesture interfere with top bar taps [Jonas D.; #552]
* Always use symbolic user icon in system menu [Florian; #957]
* Add flags parameter in GrabAccelerators API [Andrea; #68]
* Misc. bug fixes and cleanups [Florian, Jonas A.; !399, !398, !400, !402,
!407, !410, !411]
Contributors:
Jonas Ådahl, Andrea Azzarone, Arnaud Bonatti, Jonas Dreßler, Florian Müllner
Translators:
Jordi Mas [ca], Ryuta Fujii [ja], Marek Cernocky [cs], Fran Dieguez [gl],
Jiri Grönroos [fi], Serdar Sağlam [tr], Anders Jonsson [sv],
Matej Urbančič [sl], Gun Chleoc [gd], Kukuh Syafaat [id],
Baurzhan Muftakhidinov [kk], Alan Mortensen [da], Rafael Fontenelle [pt_BR],
Sveinn í Felli [is]
3.31.90
=======
* Fix input methods after ibus restarts [Takao; #295]
* Refresh world clocks and weather sections [Florian; #262]
* Port to ES6 classes (update your extensions!) [Florian; !361]
* networkAgent: Advise users when WPS support is available [Lubomir; !329]
* Performance improvements [Carlos; #832, #815]
* Fix drag-and-drop with wacom pens [Carlos; #540]
* Fix CAPS LOCK indication on wayland [Carlos; #762881]
* Show details of non-sensitive notifications on lock screen [Philip; #726]
* Refine extension-prefs' error UI [Florian; !193]
* Add switch-to-application-n keybindings [Florian; #648000]
* Remove top bar translucency [Florian; #408]
* Support emojis and keypads in on-screen keyboard [Carlos; #675]
* Don't allow popups to re-enable keyboard shortcuts on lock screen
(CVE-2019-3820) [Florian, Ray; #851]
* Replace app menu [Florian; #624]
* Include commonly copied+pasted extension helpers [Florian; !150]
* Misc. bug fixes and cleanups [Florian, Daniel, Philip, Sergio, Pascal,
Georges, verdre, Carlos, Christopher; #780, #909, !316, !308, !309, #915,
!350, !362, !357, !365, !366, !283, !367, #942, !371, !373, !374, !343,
!375, !292, !317, !377, !379, !346, !383, #953, !388]
Contributors:
Sergio Costas, Christopher Davis, Bilal Elmoussaoui, Takao Fujiwara,
Carlos Garnacho, Niels De Graef, Christian Kellner, Ignat Loskutov,
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack, Lubomir Rintel,
Jakub Steiner, Ray Strode, verdre, Daniel van Vugt, Philip Withnall
Translators:
Daniel Mustieles [es], Carmen Bianca BAKKER [eo], Charles Monzat [fr],
Pieter Schalk Schoeman [af], Jordi Mas [ca], Matej Urbančič [sl],
Fran Dieguez [gl], Balázs Úr [hu], A S Alam [pa], Fabio Tomat [fur],
Aurimas Černius [lt], Piotr Drąg [pl], Marek Cernocky [cs], Ryuta Fujii [ja]
3.31.4 3.31.4
====== ======
* Improve icon grid performance [Daniel; #174] * Improve icon grid performance [Daniel; #174]

View File

@@ -11,14 +11,6 @@ see the [project wiki][project-wiki].
Bugs should be reported to the GNOME [bug tracking system][bug-tracker]. Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
## Contributing
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/gnome-shell.
Commit messages should follow the [GNOME commit message
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
to either an issue or a merge request in each commit.
## License ## License
GNOME Shell is distributed under the terms of the GNU General Public License, GNOME Shell is distributed under the terms of the GNU General Public License,
version 2 or later. See the [COPYING][license] file for details. version 2 or later. See the [COPYING][license] file for details.

View File

@@ -1,40 +0,0 @@
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.

View File

@@ -1,208 +0,0 @@
#!/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)

View File

@@ -1,46 +1,5 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node> <node>
<!--
net.hadess.SwitcherooControl:
@short_description: D-Bus proxy to access dual-GPU controls.
After checking the availability of two switchable GPUs in the machine,
check the value of net.hadess.SwitcherooControl.HasDualGpu to see
if running applications on the discrete GPU should be offered.
The object path will be "/net/hadess/SwitcherooControl".
-->
<interface name="net.hadess.SwitcherooControl"> <interface name="net.hadess.SwitcherooControl">
<!--
HasDualGpu:
Whether two switchable GPUs are present on the system. This property
has been obsoleted in favour of the "NumGPUs" property.
-->
<property name="HasDualGpu" type="b" access="read"/> <property name="HasDualGpu" type="b" access="read"/>
<!--
NumGPUs:
The number of GPUs available on the system. Note that while having no
GPUs is unlikely, consumers of this API should probably not throw errors
if that were the case.
-->
<property name="NumGPUs" type="u" access="read"/>
<!--
GPUs:
An array of key-pair values representing each GPU. The key named "Name" (s)
will contain a user-facing name for the GPU, the "Environment" (as) key will
contain an array of even number of strings, each being an environment
variable to set to use the GPU, followed by its value, the "Default" (b) key
will tag the default (usually integrated) GPU.
-->
<property name="GPUs" type="aa{sv}" access="read"/>
</interface> </interface>
</node> </node>

View File

@@ -1,12 +0,0 @@
<node>
<interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>

View File

@@ -1,15 +0,0 @@
<node>
<!--
org.gnome.Shell.ClocksIntegration:
@short_description: Clocks integration interface
The interface used for exporting location settings to GNOME Shell's
world clocks integration.
-->
<interface name="org.gnome.Shell.ClocksIntegration">
<property name="Locations" type="av" access="read"/>
</interface>
</node>

View File

@@ -173,30 +173,6 @@
<arg type="s" direction="in" name="uuid"/> <arg type="s" direction="in" name="uuid"/>
</method> </method>
<!--
EnableExtension:
@uuid: The UUID of the extension
@success: Whether the operation was successful
Enable an extension.
-->
<method name="EnableExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<!--
DisableExtension:
@uuid: The UUID of the extension
@success: Whether the operation was successful
Disable an extension.
-->
<method name="DisableExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<!-- <!--
LaunchExtensionPrefs: LaunchExtensionPrefs:
@uuid: The UUID of the extension @uuid: The UUID of the extension
@@ -213,15 +189,6 @@
--> -->
<method name="CheckForUpdates"/> <method name="CheckForUpdates"/>
<signal name="ExtensionStateChanged">
<arg type="s" name="uuid"/>
<arg type="a{sv}" name="state"/>
</signal>
<!--
ExtensionStatusChanged:
Deprecated for ExtensionStateChanged
-->
<signal name="ExtensionStatusChanged"> <signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/> <arg type="s" name="uuid"/>
<arg type="i" name="state"/> <arg type="i" name="state"/>

View File

@@ -1,16 +0,0 @@
<node>
<!--
org.gnome.Shell.WeatherIntegration:
@short_description: Weather integration interface
The interface used for exporting location settings to GNOME Shell's
weather integration.
-->
<interface name="org.gnome.Shell.WeatherIntegration">
<property name="AutomaticLocation" type="b" access="read"/>
<property name="Locations" type="av" access="read"/>
</interface>
</node>

View File

@@ -10,6 +10,9 @@
<arg type="a{sv}" direction="in" name="params"/> <arg type="a{sv}" direction="in" name="params"/>
</method> </method>
<method name="ShowMonitorLabels"> <method name="ShowMonitorLabels">
<arg type="a{uv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels2">
<arg type="a{sv}" direction="in" name="params"/> <arg type="a{sv}" direction="in" name="params"/>
</method> </method>
<method name="HideMonitorLabels"/> <method name="HideMonitorLabels"/>
@@ -19,22 +22,17 @@
<method name="ShowApplications"/> <method name="ShowApplications"/>
<method name="GrabAccelerator"> <method name="GrabAccelerator">
<arg type="s" direction="in" name="accelerator"/> <arg type="s" direction="in" name="accelerator"/>
<arg type="u" direction="in" name="modeFlags"/> <arg type="u" direction="in" name="flags"/>
<arg type="u" direction="in" name="grabFlags"/>
<arg type="u" direction="out" name="action"/> <arg type="u" direction="out" name="action"/>
</method> </method>
<method name="GrabAccelerators"> <method name="GrabAccelerators">
<arg type="a(suu)" direction="in" name="accelerators"/> <arg type="a(su)" direction="in" name="accelerators"/>
<arg type="au" direction="out" name="actions"/> <arg type="au" direction="out" name="actions"/>
</method> </method>
<method name="UngrabAccelerator"> <method name="UngrabAccelerator">
<arg type="u" direction="in" name="action"/> <arg type="u" direction="in" name="action"/>
<arg type="b" direction="out" name="success"/> <arg type="b" direction="out" name="success"/>
</method> </method>
<method name="UngrabAccelerators">
<arg type="au" direction="in" name="action"/>
<arg type="b" direction="out" name="success"/>
</method>
<signal name="AcceleratorActivated"> <signal name="AcceleratorActivated">
<arg name="action" type="u"/> <arg name="action" type="u"/>
<arg name="parameters" type="a{sv}"/> <arg name="parameters" type="a{sv}"/>

File diff suppressed because it is too large Load Diff

View File

@@ -39,8 +39,6 @@
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Rfkill.xml</file> <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Rfkill.xml</file>
<file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file> <file preprocess="xml-stripblanks">org.gnome.SettingsDaemon.Wacom.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.AudioDeviceSelection.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.CalendarServer.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.ClocksIntegration.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Extensions.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Introspect.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file>
@@ -49,7 +47,6 @@
<file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Screenshot.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Screenshot.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.WeatherIntegration.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.xml</file>
<file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file> <file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file>
<file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file> <file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file>

View File

@@ -1,15 +0,0 @@
[Unit]
Description=Disable GNOME Shell extensions after failure
# Note that this unit must not conflict with anything, and must
# be able to run in parallel with the gnome-session-shutdown.target.
DefaultDependencies=no
# We want to disable extensions only if gnome-shell has flagged the extensions
# to be a likely cause of trouble.
ConditionPathExists=%t/gnome-shell-disable-extensions
[Service]
Type=simple
# Disable extensions
ExecStart=gsettings set org.gnome.shell disable-user-extensions true
Restart=no

View File

@@ -6,7 +6,6 @@
<file>be.json</file> <file>be.json</file>
<file>bg.json</file> <file>bg.json</file>
<file>by.json</file> <file>by.json</file>
<file>ca.json</file>
<file>cz.json</file> <file>cz.json</file>
<file>de.json</file> <file>de.json</file>
<file>dk.json</file> <file>dk.json</file>
@@ -55,6 +54,5 @@
<file>us.json</file> <file>us.json</file>
<file>vn.json</file> <file>vn.json</file>
<file>za.json</file> <file>za.json</file>
<file>emoji.json</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@@ -20,16 +20,12 @@
<file>no-notifications.svg</file> <file>no-notifications.svg</file>
<file>noise-texture.png</file> <file>noise-texture.png</file>
<file>pad-osd.css</file> <file>pad-osd.css</file>
<file alias="icons/pointer-double-click-symbolic.svg">pointer-double-click-symbolic.svg</file>
<file alias="icons/pointer-drag-symbolic.svg">pointer-drag-symbolic.svg</file>
<file alias="icons/pointer-primary-click-symbolic.svg">pointer-primary-click-symbolic.svg</file>
<file alias="icons/pointer-secondary-click-symbolic.svg">pointer-secondary-click-symbolic.svg</file>
<file>process-working.svg</file> <file>process-working.svg</file>
<file>toggle-off.svg</file> <file>toggle-off-us.svg</file>
<file>toggle-off-dark.svg</file> <file>toggle-off-intl.svg</file>
<file>toggle-off-hc.svg</file> <file>toggle-off-hc.svg</file>
<file>toggle-on.svg</file> <file>toggle-on-us.svg</file>
<file>toggle-on-dark.svg</file> <file>toggle-on-intl.svg</file>
<file>toggle-on-hc.svg</file> <file>toggle-on-hc.svg</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@@ -1,27 +0,0 @@
[Unit]
Description=GNOME Shell on Wayland
# On wayland, force a session shutdown
OnFailure=gnome-shell-disable-extensions.service gnome-session-shutdown.target
OnFailureJobMode=replace-irreversibly
CollectMode=inactive-or-failed
RefuseManualStart=on
RefuseManualStop=on
After=gnome-session-manager.target
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
# The units already conflict because they use the same BusName
#Conflicts=gnome-shell-x11.service
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On wayland we cannot restart
Restart=no
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@@ -1,10 +1,5 @@
[Unit] [Unit]
Description=GNOME Shell on Wayland Description=GNOME Shell (wayland sync point)
DefaultDependencies=no After=gnome-shell.service
BindsTo=gnome-shell.service
Requisite=gnome-session-initialized.target Conflicts=gnome-shell-x11.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
Requires=gnome-shell-wayland.service
After=gnome-shell-wayland.service

View File

@@ -1,33 +0,0 @@
[Unit]
Description=GNOME Shell on X11
# On X11, try to show the GNOME Session Failed screen
OnFailure=gnome-shell-disable-extensions.service gnome-session-failed.target
OnFailureJobMode=replace
CollectMode=inactive-or-failed
RefuseManualStart=on
RefuseManualStop=on
After=gnome-session-manager.target
Requisite=gnome-session-initialized.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
# The units already conflict because they use the same BusName
#Conflicts=gnome-shell-wayland.service
# Limit startup frequency more than the default
StartLimitIntervalSec=15s
StartLimitBurst=3
[Service]
Type=notify
ExecStart=@bindir@/gnome-shell
# Exit code 1 means we are probably *not* dealing with an extension failure
SuccessExitStatus=1
# On X11 we want to restart on-success (Alt+F2 + r) and on-failure.
Restart=always
# Do not wait before restarting the shell
RestartSec=0ms
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@@ -1,10 +1,5 @@
[Unit] [Unit]
Description=GNOME Shell on X11 Description=GNOME Shell (x11 sync point)
DefaultDependencies=no After=gnome-shell.service
BindsTo=gnome-shell.service
Requisite=gnome-session-initialized.target Conflicts=gnome-shell-wayland.target
PartOf=gnome-session-initialized.target
Before=gnome-session-initialized.target
Requires=gnome-shell-x11.service
After=gnome-shell-x11.service

View File

@@ -0,0 +1,11 @@
[Unit]
Description=GNOME Shell
Wants=gnome-session.service
After=graphical-session-pre.target gnome-session-bus.target
PartOf=graphical-session.target
[Service]
Type=dbus
ExecStart=@bindir@/gnome-shell
Restart=on-failure
BusName=org.gnome.Shell

View File

@@ -14,8 +14,6 @@ desktopconf = configuration_data()
# file when built in a non-system prefix # file when built in a non-system prefix
desktopconf.set('bindir', bindir) desktopconf.set('bindir', bindir)
desktopconf.set('VERSION', meson.project_version()) desktopconf.set('VERSION', meson.project_version())
desktopconf.set('systemd_hidden', have_systemd ? 'true' : 'false')
foreach desktop_file : desktop_files foreach desktop_file : desktop_files
i18n.merge_file('desktop', i18n.merge_file('desktop',
input: configure_file( input: configure_file(
@@ -24,7 +22,7 @@ foreach desktop_file : desktop_files
configuration: desktopconf configuration: desktopconf
), ),
output: desktop_file, output: desktop_file,
po_dir: po_dir, po_dir: '../po',
install: true, install: true,
install_dir: desktopdir, install_dir: desktopdir,
type: 'desktop' type: 'desktop'
@@ -100,23 +98,15 @@ if have_systemd
unitconf = configuration_data() unitconf = configuration_data()
unitconf.set('bindir', bindir) unitconf.set('bindir', bindir)
configure_file( unit = configure_file(
input: 'gnome-shell-x11.service.in', input: 'gnome-shell.service.in',
output: 'gnome-shell-x11.service', output: 'gnome-shell.service',
configuration: unitconf, configuration: unitconf,
install_dir: systemduserunitdir install_dir: systemduserunitdir
) )
configure_file( units = files('gnome-shell-wayland.target',
input: 'gnome-shell-wayland.service.in', 'gnome-shell-x11.target')
output: 'gnome-shell-wayland.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
units = files('gnome-shell-x11.target',
'gnome-shell-wayland.target',
'gnome-shell-disable-extensions.service')
install_data(units, install_dir: systemduserunitdir) install_data(units, install_dir: systemduserunitdir)
endif endif

View File

@@ -14,4 +14,3 @@ X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Provides=panel;windowmanager; X-GNOME-Provides=panel;windowmanager;
X-GNOME-Autostart-Notify=true X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=false X-GNOME-AutoRestart=false
X-GNOME-HiddenUnderSystemd=@systemd_hidden@

View File

@@ -21,17 +21,6 @@
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell. EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell.
</description> </description>
</key> </key>
<key name="disabled-extensions" type="as">
<default>[]</default>
<summary>UUIDs of extensions to force disabling</summary>
<description>
GNOME Shell extensions have a UUID property; this key lists extensions
which should be disabled, even if loaded as part of the current mode.
You can also manipulate this list with the EnableExtension and
DisableExtension D-Bus methods on org.gnome.Shell.
This key takes precedence over the “enabled-extensions” setting.
</description>
</key>
<key name="disable-user-extensions" type="b"> <key name="disable-user-extensions" type="b">
<default>false</default> <default>false</default>
<summary>Disable user extensions</summary> <summary>Disable user extensions</summary>
@@ -50,7 +39,7 @@
</description> </description>
</key> </key>
<key name="favorite-apps" type="as"> <key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'org.gnome.Shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default> <default>[ 'epiphany.desktop', 'evolution.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]</default>
<summary>List of desktop file IDs for favorite applications</summary> <summary>List of desktop file IDs for favorite applications</summary>
<description> <description>
The applications corresponding to these identifiers The applications corresponding to these identifiers
@@ -110,17 +99,11 @@
</description> </description>
</key> </key>
<child name="keybindings" schema="org.gnome.shell.keybindings"/> <child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
</schema> </schema>
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/" <schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">
<key name="open-application-menu" type="as">
<default>["&lt;Super&gt;F10"]</default>
<summary>Keybinding to open the application menu</summary>
<description>
Keybinding to open the application menu.
</description>
</key>
<key name="toggle-application-view" type="as"> <key name="toggle-application-view" type="as">
<default>["&lt;Super&gt;a"]</default> <default>["&lt;Super&gt;a"]</default>
<summary>Keybinding to open the “Show Applications” view</summary> <summary>Keybinding to open the “Show Applications” view</summary>
@@ -150,41 +133,21 @@
Keybinding to focus the active notification. Keybinding to focus the active notification.
</description> </description>
</key> </key>
<key name="switch-to-application-1" type="as"> <key name="pause-resume-tweens" type="as">
<default>["&lt;Super&gt;1"]</default> <default>[]</default>
<summary>Switch to application 1</summary> <summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
<description></description>
</key> </key>
<key name="switch-to-application-2" type="as"> </schema>
<default>["&lt;Super&gt;2"]</default>
<summary>Switch to application 2</summary> <schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
</key> gettext-domain="@GETTEXT_PACKAGE@">
<key name="switch-to-application-3" type="as"> <key name="keyboard-type" type="s">
<default>["&lt;Super&gt;3"]</default> <default>'touch'</default>
<summary>Switch to application 3</summary> <summary>Which keyboard to use</summary>
</key> <description>
<key name="switch-to-application-4" type="as"> The type of keyboard to use.
<default>["&lt;Super&gt;4"]</default> </description>
<summary>Switch to application 4</summary>
</key>
<key name="switch-to-application-5" type="as">
<default>["&lt;Super&gt;5"]</default>
<summary>Switch to application 5</summary>
</key>
<key name="switch-to-application-6" type="as">
<default>["&lt;Super&gt;6"]</default>
<summary>Switch to application 6</summary>
</key>
<key name="switch-to-application-7" type="as">
<default>["&lt;Super&gt;7"]</default>
<summary>Switch to application 7</summary>
</key>
<key name="switch-to-application-8" type="as">
<default>["&lt;Super&gt;8"]</default>
<summary>Switch to application 8</summary>
</key>
<key name="switch-to-application-9" type="as">
<default>["&lt;Super&gt;9"]</default>
<summary>Switch to application 9</summary>
</key> </key>
</schema> </schema>
@@ -228,36 +191,6 @@
</key> </key>
</schema> </schema>
<schema id="org.gnome.shell.world-clocks" path="/org/gnome/shell/world-clocks/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="locations" type="av">
<summary>Locations</summary>
<description>
The locations to show in world clocks
</description>
<default>[]</default>
</key>
</schema>
<schema id="org.gnome.shell.weather" path="/org/gnome/shell/weather/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="automatic-location" type="b">
<summary>Automatic location</summary>
<description>
Whether to fetch the current location or not
</description>
<default>false</default>
</key>
<key name="locations" type="av">
<summary>Location</summary>
<description>
The location for which to show a forecast
</description>
<default>[]</default>
</key>
</schema>
<!-- unused, change 00_org.gnome.shell.gschema.override instead --> <!-- unused, change 00_org.gnome.shell.gschema.override instead -->
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/" <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">

View File

@@ -1,599 +0,0 @@
{
"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"
}

View File

@@ -6,20 +6,10 @@
"rows": [ "rows": [
[ [
[ [
"a", "q"
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
], ],
[ [
"z" "w"
], ],
[ [
"e", "e",
@@ -81,7 +71,17 @@
], ],
[ [
[ [
"q" "a",
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
], ],
[ [
"s" "s"
@@ -106,14 +106,11 @@
], ],
[ [
"l" "l"
],
[
"m"
] ]
], ],
[ [
[ [
"w" "z"
], ],
[ [
"x" "x"
@@ -134,11 +131,7 @@
"n" "n"
], ],
[ [
"'", "m"
"",
"",
"",
""
] ]
], ],
[ [
@@ -168,20 +161,10 @@
"rows": [ "rows": [
[ [
[ [
"A", "Q"
"À",
"Â",
"%",
"Æ",
"Á",
"Ä",
"Ã",
"Å",
"Ā",
"ª"
], ],
[ [
"Z" "W"
], ],
[ [
"E", "E",
@@ -243,7 +226,17 @@
], ],
[ [
[ [
"Q" "A",
"À",
"Â",
"%",
"Æ",
"Á",
"Ä",
"Ã",
"Å",
"Ā",
"ª"
], ],
[ [
"S" "S"
@@ -268,14 +261,11 @@
], ],
[ [
"L" "L"
],
[
"M"
] ]
], ],
[ [
[ [
"W" "Z"
], ],
[ [
"X" "X"
@@ -296,11 +286,7 @@
"N" "N"
], ],
[ [
"'", "M"
"",
"",
"",
""
] ]
], ],
[ [
@@ -383,10 +369,10 @@
"#" "#"
], ],
[ [
"", "$",
"¢", "¢",
"£", "£",
"$", "",
"¥", "¥",
"₱" "₱"
], ],
@@ -524,16 +510,15 @@
[ [
"£" "£"
], ],
[
"¢"
],
[
"€"
],
[ [
"¥" "¥"
], ],
[
"$",
"¢"
],
[
"¢"
],
[ [
"^", "^",
"↑", "↑",
@@ -609,6 +594,6 @@
] ]
} }
], ],
"locale": "fr", "locale": "fr-CA",
"name": "French" "name": "French Canada"
} }

View File

@@ -1,5 +1,3 @@
$variant: 'light';
@import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors @import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors
@import "gnome-shell-sass/_drawing"; @import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common"; @import "gnome-shell-sass/_common";

View File

@@ -2,34 +2,33 @@
// it gets @if ed depending on $variant // it gets @if ed depending on $variant
$base_color: if($variant == 'light', #ffffff, lighten(desaturate(#241f31, 20%), 2%)); $base_color: if($variant =='light', #ffffff, #292929);
$bg_color: if($variant == 'light', #f6f5f4, darken(desaturate(#3d3846, 100%), 4%)); $bg_color: if($variant =='light', #ededed, #393f3f);
$fg_color: if($variant == 'light', #2e3436, #eeeeec); $fg_color: if($variant =='light', #2e3436, #eeeeec);
$selected_fg_color: #ffffff; $selected_fg_color: #ffffff;
$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 10%)); $selected_bg_color: if($variant == 'light', #4a90d9, darken(#4a90d9,20%));
$selected_borders_color: if($variant== 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%)); $selected_borders_color: if($variant=='light', darken($selected_bg_color, 30%),
$borders_color: if($variant == 'light', darken($bg_color, 18%), darken($bg_color, 10%)); darken($selected_bg_color, 20%));
$borders_edge: if($variant == 'light', transparentize(white, 0.2), transparentize($fg_color, 0.93)); $borders_color: if($variant =='light', darken($bg_color,30%), darken($bg_color,12%));
$link_color: if($variant == 'light', darken($selected_bg_color, 10%), lighten($selected_bg_color, 20%)); $borders_edge: if($variant =='light', white, transparentize($fg_color, 0.9));
$link_visited_color: if($variant == 'light', darken($selected_bg_color, 20%), lighten($selected_bg_color, 10%)); $link_color: if($variant == 'light', darken($selected_bg_color,10%),
lighten($selected_bg_color,20%));
$link_visited_color: if($variant == 'light', darken($selected_bg_color,20%),
lighten($selected_bg_color,10%));
$top_hilight: $borders_edge; $top_hilight: $borders_edge;
$warning_color: #f57900; $warning_color: #f57900;
$error_color: #ff8080; $error_color: #cc0000;
$success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%)); $success_color: if($variant =='light', #73d216, darken(#73d216,10%));
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%)); $destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
$osd_fg_color: #eeeeec; $osd_fg_color: #eeeeec;
$osd_text_color: white; $osd_bg_color: #2e3436;
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 12%),0.04);
$osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5);
$osd_insensitive_fg_color: mix($osd_fg_color, opacify($osd_bg_color, 1), 50%);
$osd_borders_color: transparentize(black, 0.3); $osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.84); $osd_outer_borders_color: transparentize(white, 0.9);
$tooltip_borders_color: $osd_outer_borders_color; $tooltip_borders_color: $osd_outer_borders_color;
$shadow_color: transparentize(black, 0.9);
//insensitive state derived colors //insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%); $insensitive_fg_color: mix($fg_color, $bg_color, 50%);

File diff suppressed because it is too large Load Diff

View File

@@ -37,13 +37,16 @@
// possible $t values: // possible $t values:
// normal, focus, insensitive // normal, focus, insensitive
// //
$_inner_shadows: inset 0 2px 4px transparentize(black, 0.6);
@if $t==normal { @if $t==normal {
background-color: $base_color; background-color: $base_color;
border-color: $borders_color; border-color: $borders_color;
@include _shadows($_inner_shadows);
} }
@if $t==focus { @if $t==focus {
@include _shadows($_inner_shadows);
border-color: if($fc==$selected_bg_color, border-color: if($fc==$selected_bg_color,
$selected_borders_color, $selected_borders_color,
darken($fc,35%)); darken($fc,35%));
@@ -108,7 +111,7 @@
} }
} }
@mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: $borders_edge) { @mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
// //
// Button drawing function // Button drawing function
// //
@@ -127,17 +130,19 @@
$_hilight_color: _button_hilight_color($c); $_hilight_color: _button_hilight_color($c);
$_button_edge: if($edge == none, none, _widget_edge($edge)); $_button_edge: if($edge == none, none, _widget_edge($edge));
$_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1))); $_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
$_button_shadow: 0 1px 2px transparentize($shadow_color, 0.03);
@if $t==normal { @if $t==normal {
// //
// normal button // normal button
// //
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
color: $tc; color: $osd_fg_color;
background-color: $c; background-color: $_bg;
border-color: $borders_color; border-color: $osd_borders_color;
box-shadow: $_button_shadow; box-shadow: inset 0 1px lighten($osd_bg_color,10%);
text-shadow: 0 1px black; text-shadow: 0 1px black;
icon-shadow: 0 1px black; icon-shadow: 0 1px black;
} }
@@ -145,21 +150,26 @@
// //
// focused button // focused button
// //
color: $tc; $_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
color: $osd_fg_color;
text-shadow: 0 1px black; text-shadow: 0 1px black;
icon-shadow: 0 1px black; icon-shadow: 0 1px black;
box-shadow: inset 0px 0px 0px 2px $selected_bg_color; box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
//border-color: $selected_bg_color;
} }
@else if $t==hover { @else if $t==hover {
// //
// active osd button // active osd button
// //
color: $tc; $_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
border-color: $borders_color; lighten($osd_bg_color,3%));
background-color: $c;
box-shadow: $_button_shadow; color: white;
border-color: $osd_borders_color;
background-color: $_bg;
box-shadow: inset 0 1px lighten($osd_bg_color,20%);
text-shadow: 0 1px black; text-shadow: 0 1px black;
icon-shadow: 0 1px black; icon-shadow: 0 1px black;
@@ -168,18 +178,27 @@
// //
// active osd button // active osd button
// //
color: $tc; $_bg: if($c!=$bg_color, $c, $osd_borders_color);
border-color: $borders_color;
background-color: $c; color: white;
border-color: $osd_borders_color;
background-color: $selected_bg_color;
// This should be none, but it's creating some issues with borders, so to
// workaround it for now, use inset wich goes through a different code path.
// see https://bugzilla.gnome.org/show_bug.cgi?id=752934
box-shadow: inset 0 0 black;
text-shadow: none; text-shadow: none;
icon-shadow: none; icon-shadow: none;
box-shadow: none;
} }
@else if $t==insensitive { @else if $t==insensitive {
//
// insensitive osd button
//
$_bg: transparentize(mix($insensitive_fg_color,$osd_bg_color,20%),0.3);
color: $insensitive_fg_color; color: $insensitive_fg_color;
border-color: $insensitive_borders_color; border-color: $osd_borders_color;
background-color: $insensitive_bg_color; background-color: $_bg;
box-shadow: none; box-shadow: none;
text-shadow: none; text-shadow: none;
icon-shadow: none; icon-shadow: none;

View File

@@ -26,7 +26,6 @@ $osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9); $osd_outer_borders_color: transparentize(white, 0.9);
$tooltip_borders_color: $osd_outer_borders_color; $tooltip_borders_color: $osd_outer_borders_color;
$shadow_color: transparentize(black, 0.9);
//insensitive state derived colors //insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%); $insensitive_fg_color: mix($fg_color, $bg_color, 50%);

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2">
<g
id="layer1"
style="display:inline">
<g
id="id1"
transform="translate(-19,-0.75)">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 19.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.38151 2.829427,-2.763021 4.24414,-4.144531 0.5882,1.18866 1.158389,2.386561 1.758464,3.569127 1.108631,1.640259 4.157538,0.465128 3.89799,-1.495859 0.01057,-0.470226 -0.405577,-0.908445 -0.434651,-1.313638 0.259401,-0.25321 0.518802,-0.50642 0.778203,-0.75963 0.5882,1.18866 1.158389,2.386561 1.758464,3.569127 1.108631,1.640259 4.157538,0.465128 3.89799,-1.495859 -0.192325,-0.904303 -0.717854,-1.698026 -1.068629,-2.548967 -0.238908,-0.512658 -0.477817,-1.025315 -0.716725,-1.537973 1.755859,0 3.511719,0 5.267578,0 C 34.777352,9.738932 30.31641,5.0970051 25.855469,0.45507812 c 0,2.08138018 0,4.16276048 0,6.24414068 -2,-2.0813802 -4,-4.1627605 -6,-6.24414068 z m 1.5,3.72656248 c 2,2.0813801 4,4.1627603 6,6.2441404 0,-2.0813801 0,-4.1627603 0,-6.2441404 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.366537,0 -2.733073,0 -4.09961,0 0.883468,1.903435 1.781983,3.800273 2.656081,5.707817 0.0065,0.622781 -1.227555,0.980575 -1.325116,0.207118 -0.80433,-1.640251 -1.608661,-3.280501 -2.412991,-4.920752 -1.020182,0.995443 -2.040365,1.990885 -3.060547,2.986328 0.263642,0.608048 0.596803,1.192457 0.814693,1.816134 -0.182662,0.601037 -1.26833,0.8373 -1.365856,0.06795 -0.796094,-1.623456 -1.592189,-3.246912 -2.388284,-4.870368 -1.059245,1.033854 -2.118489,2.067708 -3.177734,3.101562 -4e-6,-4.265002 -7e-6,-8.5300036 -1.1e-5,-12.7950054 z"
id="path5565" />
</g>
<g
id="id2"
transform="translate(-25,-0.75)" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2">
<g
id="g835">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="M 10.705078 1.671875 C 9.8685536 1.7465699 8.886927 1.5353073 8.2578125 2.2480469 C 8.0785627 2.7511513 7.8667422 2.9777446 7.3125 2.8652344 C 6.5186841 2.8141575 5.6105879 2.9190179 5.125 3.6386719 C 4.5700923 4.4696324 4.8113194 5.4949043 4.7578125 6.4316406 L 4.7578125 7.9335938 C 4.2480917 7.6156216 3.6258927 7.8015358 3.0585938 7.7519531 C 2.6157606 7.7312277 2.1774807 7.7771069 1.7402344 7.84375 C 1.7971654 10.529678 1.813967 13.217089 1.8613281 15.902344 C 1.9550191 17.204635 3.0933719 18.307155 4.40625 18.326172 C 5.0391993 18.341272 5.8885801 18.332951 6.6308594 18.337891 C 9.8526764 18.325821 13.076973 18.38774 16.296875 18.28125 C 17.459088 18.161027 18.510143 17.092798 18.367188 15.884766 L 18.367188 6.4042969 C 17.660379 5.4636119 16.551912 4.623434 15.308594 4.8339844 C 15.009045 4.3804158 14.822476 3.3608651 14.082031 3.0351562 C 13.727176 2.744118 13.242443 2.9253873 12.822266 2.8730469 C 12.524824 2.8003648 11.966366 3.0655864 11.953125 2.6210938 C 11.795774 2.0995736 11.23789 1.7125276 10.705078 1.671875 z M 10.599609 3.1757812 C 10.764131 3.4472414 10.782382 3.9294982 10.818359 4.3007812 C 10.824915 4.3076775 10.838155 4.3066925 10.845703 4.3125 C 10.836598 4.3123268 10.827465 4.3126732 10.818359 4.3125 L 11.3125 10.212891 L 11.976562 4.3710938 L 13.322266 4.375 C 13.858345 4.7645492 13.735252 5.5154752 13.876953 6.0976562 C 13.865826 6.1651282 13.88335 6.1937019 13.892578 6.234375 C 13.891928 6.2343667 13.891276 6.2343833 13.890625 6.234375 L 13.902344 6.3203125 L 14.384766 10.185547 L 15.048828 6.265625 C 15.622863 6.228498 16.206517 6.3041365 16.607422 6.7675781 C 17.017062 6.9844433 16.823063 7.4565491 16.867188 7.8261719 L 16.867188 16.167969 C 16.530129 17.131654 15.267211 16.71624 14.492188 16.828125 C 11.121671 16.841205 7.7500508 16.861953 4.3808594 16.814453 C 3.4051926 16.786173 3.2389196 15.744474 3.3398438 14.972656 C 3.3282027 13.065594 3.2950998 11.158732 3.2617188 9.2519531 C 3.5880829 9.2584131 3.9376766 9.2391948 4.25 9.2617188 C 4.7438842 10.17694 4.7346154 11.262903 4.7578125 12.277344 C 5.2504494 12.270544 5.8011939 12.317174 6.2578125 12.277344 C 6.2669593 9.7577406 6.2393741 7.2373172 6.2714844 4.71875 C 6.3763823 4.198849 7.0022289 4.409587 7.3828125 4.3652344 L 8.0585938 4.3652344 L 8.546875 10.212891 L 9.2167969 4.3359375 L 9.2128906 4.3359375 C 9.2438386 3.9531035 9.0622615 3.4401006 9.4609375 3.2167969 L 10.599609 3.1757812 z "
id="path5630" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2"
version="1.1">
<g
id="layer1"
style="display:inline">
<g
id="id1"
transform="translate(-22.25,-0.75)">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 25.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.380859 2.829427,-2.761719 4.24414,-4.142578 0.612408,1.215372 1.173049,2.460221 1.819709,3.656095 1.141947,1.476279 3.975266,0.389006 3.846009,-1.473608 -0.09413,-0.822519 -0.594755,-1.521423 -0.899969,-2.277599 -0.298869,-0.640171 -0.597739,-1.280342 -0.896608,-1.920513 1.75651,0 3.513021,0 5.269531,0 C 34.777344,9.738932 30.316406,5.0970051 25.855469,0.45507812 Z m 1.5,3.72656248 c 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.367188,0 -2.734375,0 -4.101563,0 0.885072,1.903196 1.781799,3.80152 2.659622,5.707744 0.0349,0.566084 -1.149057,0.988823 -1.282093,0.297971 -0.818567,-1.671162 -1.637133,-3.342323 -2.455699,-5.013485 -1.059896,1.034505 -2.119791,2.06901 -3.179687,3.103515 1.5e-5,-4.264988 3e-5,-8.5299756 4.5e-5,-12.7949634 z"
id="path5565" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2">
<g
id="layer1"
style="display:inline;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke:#000000;stroke-opacity:1">
<g
transform="matrix(-1,0,0,1,42,-0.75)"
id="g5847"
style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke:#000000;stroke-opacity:1">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 25.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.380859 2.829427,-2.761719 4.24414,-4.142578 0.612408,1.215372 1.173049,2.460221 1.819709,3.656095 1.141947,1.476279 3.975266,0.389006 3.846009,-1.473608 -0.09413,-0.822519 -0.594755,-1.521423 -0.899969,-2.277599 -0.298869,-0.640171 -0.597739,-1.280342 -0.896608,-1.920513 1.75651,0 3.513021,0 5.269531,0 C 34.777344,9.738932 30.316406,5.0970051 25.855469,0.45507812 Z m 1.5,3.72656248 c 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.367188,0 -2.734375,0 -4.101563,0 0.885072,1.903196 1.781799,3.80152 2.659622,5.707744 0.0349,0.566084 -1.149057,0.988823 -1.282093,0.297971 -0.818567,-1.671162 -1.637133,-3.342323 -2.455699,-5.013485 -1.059896,1.034505 -2.119791,2.06901 -3.179687,3.103515 1.5e-5,-4.264988 3e-5,-8.5299756 4.5e-5,-12.7949634 z"
id="path5851" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="22"><defs><linearGradient id="a"><stop offset="0" stop-color="#39393a"/><stop offset="1" stop-color="#302f30"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="53" y1="294.429" x2="53" y2="309.804" gradientUnits="userSpaceOnUse" gradientTransform="translate(-42.76)"/></defs><g transform="translate(0 -291.18)" stroke-width="1.085"><rect style="marker:none" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#323233" stroke="#272728"/><rect ry="10.455" rx="10.455" y="291.715" x=".543" height="20.911" width="21.143" style="marker:none" fill="url(#b)" stroke="#151515"/></g></svg>

Before

Width:  |  Height:  |  Size: 725 B

View File

@@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="toggle-off-us.svg">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4-0"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802-8"
id="linearGradient12311-3-1-0-5-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802-8"
inkscape:collect="always">
<stop
id="stop37804-1"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806-8"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="492.52756"
x2="610.13782"
y1="501.43866"
x1="610.13782"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
gradientUnits="userSpaceOnUse"
id="linearGradient13602"
xlink:href="#linearGradient37802-8"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-5.0602834"
inkscape:cy="16.473273"
inkscape:document-units="px"
inkscape:current-layer="g37994"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2862">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
</g>
<g
transform="translate(-49.946213,-1.890275)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g>
<path
sodipodi:type="arc"
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:2.15627193;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="path13479"
sodipodi:cx="16.4375"
sodipodi:cy="10.8125"
sodipodi:rx="4.3125"
sodipodi:ry="4.3125"
d="m 20.75,10.8125 a 4.3125,4.3125 0 1 1 -8.625,0 4.3125,4.3125 0 1 1 8.625,0 z"
transform="matrix(1.4212691,0,0,1.1514287,577.38488,1761.1138)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@@ -0,0 +1,255 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="toggle-on-intl.svg">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802"
id="linearGradient12311-3-1-0-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802"
inkscape:collect="always">
<stop
id="stop37804"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4-3"
id="linearGradient77680"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.0322581,717.71949,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4-3">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5-7" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0-9" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4-0"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient37802-8"
id="linearGradient12311-3-1-0-5-4"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-256.56122,59.071426)"
x1="610.13782"
y1="501.43866"
x2="610.13782"
y2="492.52756" />
<linearGradient
id="linearGradient37802-8"
inkscape:collect="always">
<stop
id="stop37804-1"
offset="0"
style="stop-color:#2c2c2c;stop-opacity:1" />
<stop
id="stop37806-8"
offset="1"
style="stop-color:#16191a;stop-opacity:1" />
</linearGradient>
<linearGradient
y2="492.52756"
x2="610.13782"
y1="501.43866"
x1="610.13782"
gradientTransform="matrix(1.5918367,0,0,0.85714285,-900.56122,-423.92857)"
gradientUnits="userSpaceOnUse"
id="linearGradient13602"
xlink:href="#linearGradient37802-8"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="16.760995"
inkscape:cy="21.955673"
inkscape:document-units="px"
inkscape:current-layer="g37994"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1375"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2862">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient12311-3-1-0-5-4);fill-opacity:1;fill-rule:nonzero;stroke:#16191a;stroke-width:1.37920942;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new" />
</g>
<g
transform="translate(-49.946213,-1.890275)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g>
<text
xml:space="preserve"
style="font-size:13.79166794px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
x="520.29974"
y="1997.0011"
id="text75614"
sodipodi:linespacing="125%"
transform="scale(1.1236771,0.88993537)"><tspan
sodipodi:role="line"
id="tspan75616"
x="520.29974"
y="1997.0011">OFF</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="22"><g transform="translate(0 -291.18)"><rect style="marker:none;font-variant-east_asian:normal" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#e1dedb" stroke="#cdc7c2" stroke-linecap="round" stroke-linejoin="round"/><rect ry="10.455" rx="10.455" y="291.715" x=".543" height="20.911" width="21.143" style="marker:none;font-variant-east_asian:normal" fill="#f8f7f7" stroke="#aa9f98" stroke-linecap="round" stroke-linejoin="round"/><g transform="matrix(.97148 0 0 1 1658.914 -2552.91)" stroke-width="1.015" stroke-linecap="round" stroke-linejoin="round"><rect ry="13.17" rx="13.556" y="1234.681" x="-1242.732" height="26" width="49.409" style="marker:none" fill="#e1dedb" stroke="#cdc7c2"/><rect style="marker:none" width="26.763" height="26" x="-1242.732" y="1234.769" rx="13.511" ry="13.126" fill="#f8f7f7" stroke="#aa9f98"/></g><g transform="matrix(.97148 0 0 1 1658.914 -2512.91)" stroke-width="1.015" stroke="#2b73cc"><rect style="marker:none" width="49.409" height="26" x="-1242.732" y="1234.681" rx="13.556" ry="13.17" fill="#3081e3"/><rect ry="13.126" rx="13.511" y="1234.769" x="-1220.086" height="26" width="26.763" style="marker:none" fill="#f8f7f7" stroke-linecap="round" stroke-linejoin="round"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="22"><defs><linearGradient id="a"><stop offset="0" stop-color="#39393a"/><stop offset="1" stop-color="#302f30"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="53" y1="294.429" x2="53" y2="309.804" gradientUnits="userSpaceOnUse" gradientTransform="translate(-19)"/></defs><g transform="translate(0 -291.18)" stroke="#030e1b" stroke-width="1.085"><rect style="marker:none" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#15539e"/><rect ry="10.455" rx="10.455" y="291.715" x="24.304" height="20.911" width="21.143" style="marker:none" fill="url(#b)"/></g></svg>

Before

Width:  |  Height:  |  Size: 707 B

View File

@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="toggle-on-intl.svg">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461"
id="linearGradient77551"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3066667,0,0,1,-841.64667,-483)"
x1="1164.7644"
y1="962.93695"
x2="1164.7644"
y2="970.51404" />
<linearGradient
id="linearGradient77461"
inkscape:collect="always">
<stop
id="stop77463"
offset="0"
style="stop-color:#182f4c;stop-opacity:1" />
<stop
id="stop77465"
offset="1"
style="stop-color:#205b9a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="37.410841"
inkscape:cy="16.009314"
inkscape:document-units="px"
inkscape:current-layer="g37994"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2862">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient77551);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<g
transform="translate(2.0625,-2)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g>
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:new"
id="rect13678"
width="3.0646207"
height="12.414008"
x="554.77728"
y="1767.3566" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

207
data/theme/toggle-on-us.svg Normal file
View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="toggle-on-us.svg">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient76469-7-7-4"
id="linearGradient38024"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0215462,0,0,1.0322581,717.22867,428.68472)"
x1="6"
y1="102.95528"
x2="6"
y2="84.505203" />
<linearGradient
inkscape:collect="always"
id="linearGradient76469-7-7-4">
<stop
style="stop-color:#2e3232;stop-opacity:1"
offset="0"
id="stop76471-7-1-5" />
<stop
style="stop-color:#3e4545;stop-opacity:1"
offset="1"
id="stop76473-9-0-0" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect77541-4"
is_visible="true" />
<linearGradient
id="linearGradient77461-1"
inkscape:collect="always">
<stop
id="stop77463-1"
offset="0"
style="stop-color:#182f4c;stop-opacity:1" />
<stop
id="stop77465-4"
offset="1"
style="stop-color:#205b9a;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461-1"
id="linearGradient77551-6-5"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8527367,0,0,0.80554422,-969.41608,-778.00299)"
x1="1164.7644"
y1="962.93695"
x2="1164.7644"
y2="970.51404" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient77461-1"
id="linearGradient11198"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3066667,0,0,1,-1066.3709,794.25325)"
x1="1322.5831"
y1="-312.51855"
x2="1322.5831"
y2="-306.53461" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-26.798898"
inkscape:cy="5.3753009"
inkscape:document-units="px"
inkscape:current-layer="g37994"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:snap-nodes="false"
inkscape:snap-bbox="true"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid12954"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata2862">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
transform="matrix(0.6526046,0,0,0.80554422,99.592644,-636.32172)"
id="g37994">
<g
id="g37996"
transform="translate(-115,1277)">
<rect
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964000000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;opacity:0.19591837"
id="rect13475"
width="98"
height="25"
x="644.5"
y="484.61118"
rx="4.7429576"
ry="3.8424656" />
<rect
ry="3.8424656"
rx="4.7429576"
y="483.5"
x="644.5"
height="25"
width="98"
id="rect38000"
style="color:#000000;fill:url(#linearGradient11198);fill-opacity:1;fill-rule:nonzero;stroke:#182f4c;stroke-width:1.37920964;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;clip-rule:nonzero;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;filter-blend-mode:normal;filter-gaussianBlur-deviation:0;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto" />
</g>
<g
transform="translate(2.0625,-2)"
id="g38002">
<g
transform="translate(-115,1247)"
style="display:inline"
id="g38004">
<rect
ry="3.7972314"
rx="4.6871223"
y="515.5"
x="694.53046"
height="25"
width="45.969578"
id="rect38006"
style="color:#000000;fill:url(#linearGradient38024);fill-opacity:1;fill-rule:nonzero;stroke:#1f2020;stroke-width:1.37920964;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<path
sodipodi:nodetypes="cc"
style="opacity:0.1;color:#000000;fill:none;stroke:#ffffff;stroke-width:1.37920964px;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 699.09675,516.7365 36.86904,0"
id="path38016"
inkscape:path-effect="#path-effect77541-4"
inkscape:original-d="m 699.09675,516.7365 36.86904,0"
inkscape:connector-curvature="0" />
</g>
</g>
<text
transform="scale(1.1000946,0.90901274)"
sodipodi:linespacing="125%"
id="text38018"
y="1955.5205"
x="495.94223"
style="font-size:13.29953671px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
xml:space="preserve"><tspan
y="1955.5205"
x="495.94223"
id="tspan38020"
sodipodi:role="line">ON</tspan></text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="22"><g transform="translate(0 -291.18)" stroke="#2b73cc"><rect style="marker:none;font-variant-east_asian:normal" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#3081e3"/><rect ry="10.455" rx="10.455" y="291.715" x="24.304" height="20.911" width="21.143" style="marker:none;font-variant-east_asian:normal" fill="#f8f7f7" stroke-linecap="round" stroke-linejoin="round"/></g></svg>

Before

Width:  |  Height:  |  Size: 473 B

View File

@@ -40,7 +40,6 @@ do
done done
cat >>$TMP_GRESOURCE_FILE <<EOF cat >>$TMP_GRESOURCE_FILE <<EOF
<file>emoji.json</file>
</gresource> </gresource>
</gresources> </gresources>
EOF EOF

View File

@@ -28,7 +28,7 @@ foreach iface : ifaces
output: 'doc-gen-' + iface[1], output: 'doc-gen-' + iface[1],
command: [ command: [
'gdbus-codegen', 'gdbus-codegen',
'--interface-prefix=@0@.'.format(iface[0]), '--interface-prefix=@0@.'.format(iface),
'--generate-docbook', 'doc-gen', '--generate-docbook', 'doc-gen',
'--output-directory', '@OUTDIR@', '--output-directory', '@OUTDIR@',
'@INPUT@' '@INPUT@'

View File

@@ -31,34 +31,34 @@ its dependencies to build from tarballs.</description>
<programming-language>JavaScript</programming-language> <programming-language>JavaScript</programming-language>
<programming-language>C</programming-language> <programming-language>C</programming-language>
<author> <maintainer>
<foaf:Person> <foaf:Person>
<foaf:name>William Jon McCann</foaf:name> <foaf:name>William Jon McCann</foaf:name>
<foaf:mbox rdf:resource="mailto:jmccann@redhat.com" /> <foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
<gnome:userid>mccann</gnome:userid> <gnome:userid>mccann</gnome:userid>
</foaf:Person> </foaf:Person>
</author> </maintainer>
<author> <maintainer>
<foaf:Person> <foaf:Person>
<foaf:name>Owen Taylor</foaf:name> <foaf:name>Owen Taylor</foaf:name>
<foaf:mbox rdf:resource="mailto:otaylor@redhat.com" /> <foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
<gnome:userid>otaylor</gnome:userid> <gnome:userid>otaylor</gnome:userid>
</foaf:Person> </foaf:Person>
</author> </maintainer>
<author> <maintainer>
<foaf:Person> <foaf:Person>
<foaf:name>Colin Walters</foaf:name> <foaf:name>Colin Walters</foaf:name>
<foaf:mbox rdf:resource="mailto:walters@verbum.org" /> <foaf:mbox rdf:resource="mailto:walters@verbum.org" />
<gnome:userid>walters</gnome:userid> <gnome:userid>walters</gnome:userid>
</foaf:Person> </foaf:Person>
</author> </maintainer>
<author> <maintainer>
<foaf:Person> <foaf:Person>
<foaf:name>Marina Zhurakhinskaya</foaf:name> <foaf:name>Marina Zhurakhinskaya</foaf:name>
<foaf:mbox rdf:resource="mailto:marinaz@redhat.com" /> <foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
<gnome:userid>marinaz</gnome:userid> <gnome:userid>marinaz</gnome:userid>
</foaf:Person> </foaf:Person>
</author> </maintainer>
<maintainer> <maintainer>
<foaf:Person> <foaf:Person>
<foaf:name>Florian Müllner</foaf:name> <foaf:name>Florian Müllner</foaf:name>

View File

@@ -1,9 +1,10 @@
/* exported main */
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.Gtk = '3.0';
const Gettext = imports.gettext; const Gettext = imports.gettext;
const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi; const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const Pango = imports.gi.Pango;
const Format = imports.format; const Format = imports.format;
const _ = Gettext.gettext; const _ = Gettext.gettext;
@@ -12,8 +13,6 @@ const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions'); const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@@ -23,53 +22,74 @@ function stripPrefix(string, prefix) {
return string; return string;
} }
var Application = GObject.registerClass( var Application = class {
class Application extends Gtk.Application { constructor() {
_init() {
GLib.set_prgname('gnome-shell-extension-prefs'); GLib.set_prgname('gnome-shell-extension-prefs');
super._init({ this.application = new Gtk.Application({
application_id: 'org.gnome.shell.ExtensionPrefs', application_id: 'org.gnome.shell.ExtensionPrefs',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE, flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
}); });
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('command-line', this._onCommandLine.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
this._extensionPrefsModules = {};
this._startupUuid = null; this._startupUuid = null;
this._loaded = false; this._loaded = false;
this._skipMainWindow = false; this._skipMainWindow = false;
this._shellProxy = null;
} }
get shellProxy() { _extensionAvailable(uuid) {
return this._shellProxy; let extension = ExtensionUtils.extensions[uuid];
}
_showPrefs(uuid) { if (!extension)
let row = this._extensionSelector.get_children().find(c => {
return c.uuid === uuid && c.hasPrefs;
});
if (!row)
return false; return false;
if (!extension.dir.get_child('prefs.js').query_exists(null))
return false;
return true;
}
_getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid;
if (this._extensionPrefsModules.hasOwnProperty(uuid))
return this._extensionPrefsModules[uuid];
ExtensionUtils.installImporter(extension);
let prefsModule = extension.imports.prefs;
prefsModule.init(extension.metadata);
this._extensionPrefsModules[uuid] = prefsModule;
return prefsModule;
}
_selectExtension(uuid) {
if (!this._extensionAvailable(uuid))
return;
let extension = ExtensionUtils.extensions[uuid];
let widget; let widget;
try { try {
widget = row.prefsModule.buildPrefsWidget(); let prefsModule = this._getExtensionPrefsModule(extension);
widget = prefsModule.buildPrefsWidget();
} catch (e) { } catch (e) {
widget = this._buildErrorUI(row, e); widget = this._buildErrorUI(extension, e);
} }
let dialog = new Gtk.Window({ let dialog = new Gtk.Window({ modal: !this._skipMainWindow,
modal: !this._skipMainWindow, type_hint: Gdk.WindowTypeHint.DIALOG });
type_hint: Gdk.WindowTypeHint.DIALOG, dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true,
}); title: extension.metadata.name,
dialog.set_titlebar(new Gtk.HeaderBar({ visible: true }));
show_close_button: true,
title: row.name,
visible: true,
}));
if (this._skipMainWindow) { if (this._skipMainWindow) {
this.add_window(dialog); this.application.add_window(dialog);
if (this._window) if (this._window)
this._window.destroy(); this._window.destroy();
this._window = dialog; this._window = dialog;
@@ -81,127 +101,36 @@ class Application extends Gtk.Application {
dialog.set_default_size(600, 400); dialog.set_default_size(600, 400);
dialog.add(widget); dialog.add(widget);
dialog.show(); dialog.show();
return true;
} }
_buildErrorUI(row, exc) { _buildErrorUI(extension, exc) {
let scroll = new Gtk.ScrolledWindow({ let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true,
});
let box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60,
});
scroll.add(box);
let label = new Gtk.Label({ let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(_("Somethings gone wrong")), label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
use_markup: true,
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
box.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but theres been a problem: the settings for this extension cant be displayed. We recommend that you report the issue to the extension authors."),
justify: Gtk.Justification.CENTER,
wrap: true,
}); });
box.add(label); box.add(label);
let expander = new Expander({ let errortext = '';
label: _("Technical Details"), errortext += exc;
margin_top: 12, errortext += '\n\n';
}); errortext += 'Stack trace:\n';
box.add(expander);
let errortext = `${exc}\n\nStack trace:\n${
// Indent stack trace. // Indent stack trace.
exc.stack.split('\n').map(line => ` ${line}`).join('\n') errortext += exc.stack.split('\n').map(line => ' ' + line).join('\n');
}`;
let scroll = new Gtk.ScrolledWindow({ vexpand: true });
let buffer = new Gtk.TextBuffer({ text: errortext }); let buffer = new Gtk.TextBuffer({ text: errortext });
let textview = new Gtk.TextView({ let textview = new Gtk.TextView({ buffer: buffer });
buffer, textview.override_font(Pango.font_description_from_string('monospace'));
wrap_mode: Gtk.WrapMode.WORD, scroll.add(textview);
monospace: true, box.add(scroll);
editable: false,
top_margin: 12,
bottom_margin: 12,
left_margin: 12,
right_margin: 12,
});
let toolbar = new Gtk.Toolbar(); box.show_all();
let provider = new Gtk.CssProvider(); return box;
provider.load_from_data(`* {
border: 0 solid @borders;
border-top-width: 1px;
}`);
toolbar.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
let copyButton = new Gtk.ToolButton({
icon_name: 'edit-copy-symbolic',
tooltip_text: _("Copy Error"),
});
toolbar.add(copyButton);
copyButton.connect('clicked', w => {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${row.uuid} had an error:`,
'```', // '`' (xgettext throws up on odd number of backticks)
`${exc}`,
'```', // '`'
'',
'Stack trace:',
'```', // '`'
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```', // '`'
'',
];
clipboard.set_text(lines.join('\n'), -1);
});
let spacing = new Gtk.SeparatorToolItem({ draw: false });
toolbar.add(spacing);
toolbar.child_set_property(spacing, "expand", true);
let urlButton = new Gtk.ToolButton({
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: row.url != null,
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(row.url, context);
});
let expandedBox = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
});
expandedBox.add(textview);
expandedBox.add(toolbar);
expander.add(expandedBox);
scroll.show_all();
return scroll;
} }
_buildUI() { _buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: this, this._window = new Gtk.ApplicationWindow({ application: app,
window_position: Gtk.WindowPosition.CENTER }); window_position: Gtk.WindowPosition.CENTER });
this._window.set_default_size(800, 500); this._window.set_default_size(800, 500);
@@ -218,12 +147,8 @@ class Application extends Gtk.Application {
Gio.SettingsBindFlags.DEFAULT | Gio.SettingsBindFlags.DEFAULT |
Gio.SettingsBindFlags.INVERT_BOOLEAN); Gio.SettingsBindFlags.INVERT_BOOLEAN);
this._mainStack = new Gtk.Stack({
transition_type: Gtk.StackTransitionType.CROSSFADE,
});
this._window.add(this._mainStack);
let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER }); let scroll = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER });
this._window.add(scroll);
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE }); this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE });
this._extensionSelector.set_sort_func(this._sortList.bind(this)); this._extensionSelector.set_sort_func(this._sortList.bind(this));
@@ -231,18 +156,20 @@ class Application extends Gtk.Application {
scroll.add(this._extensionSelector); scroll.add(this._extensionSelector);
this._mainStack.add_named(scroll, 'listing');
this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell'); this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStateChanged', this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
this._onExtensionStateChanged.bind(this)); if (ExtensionUtils.extensions[uuid] !== undefined)
this._scanExtensions();
});
this._window.show_all(); this._window.show_all();
} }
_sortList(row1, row2) { _sortList(row1, row2) {
return row1.name.localeCompare(row2.name); let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
} }
_updateHeader(row, before) { _updateHeader(row, before) {
@@ -253,48 +180,19 @@ class Application extends Gtk.Application {
row.set_header(sep); row.set_header(sep);
} }
_findExtensionRow(uuid) {
return this._extensionSelector.get_children().find(c => c.uuid === uuid);
}
_onExtensionStateChanged(proxy, senderName, [uuid, newState]) {
let extension = ExtensionUtils.deserializeExtension(newState);
let row = this._findExtensionRow(uuid);
if (row) {
if (extension.state === ExtensionState.UNINSTALLED)
row.destroy();
return; // we only deal with new and deleted extensions here
}
this._addExtensionRow(extension);
}
_scanExtensions() { _scanExtensions() {
this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => { let finder = new ExtensionUtils.ExtensionFinder();
if (e) { finder.connect('extension-found', this._extensionFound.bind(this));
if (e instanceof Gio.DBusError) { finder.scanExtensions();
log(`Failed to connect to shell proxy: ${e}`);
this._mainStack.add_named(new NoShellPlaceholder(), 'noshell');
this._mainStack.visible_child_name = 'noshell';
} else {
throw e;
}
return;
}
for (let uuid in extensionsMap) {
let extension = ExtensionUtils.deserializeExtension(extensionsMap[uuid]);
this._addExtensionRow(extension);
}
this._extensionsLoaded(); this._extensionsLoaded();
});
} }
_addExtensionRow(extension) { _extensionFound(finder, extension) {
let row = new ExtensionRow(extension); let row = new ExtensionRow(extension.uuid);
row.prefsButton.visible = this._extensionAvailable(row.uuid);
row.prefsButton.connect('clicked', () => { row.prefsButton.connect('clicked', () => {
this._showPrefs(row.uuid); this._selectExtension(row.uuid);
}); });
row.show_all(); row.show_all();
@@ -302,31 +200,24 @@ class Application extends Gtk.Application {
} }
_extensionsLoaded() { _extensionsLoaded() {
if (this._extensionSelector.get_children().length > 0) if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._mainStack.visible_child_name = 'listing'; this._selectExtension(this._startupUuid);
else
this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid)
this._showPrefs(this._startupUuid);
this._startupUuid = null; this._startupUuid = null;
this._skipMainWindow = false; this._skipMainWindow = false;
this._loaded = true; this._loaded = true;
} }
vfunc_activate() { _onActivate() {
this._window.present(); this._window.present();
} }
vfunc_startup() { _onStartup(app) {
super.vfunc_startup(); this._buildUI(app);
this._buildUI();
this._scanExtensions(); this._scanExtensions();
} }
vfunc_command_line(commandLine) { _onCommandLine(app, commandLine) {
this.activate(); app.activate();
let args = commandLine.get_arguments(); let args = commandLine.get_arguments();
if (args.length) { if (args.length) {
@@ -337,208 +228,16 @@ class Application extends Gtk.Application {
// Strip off "extension:///" prefix which fakes a URI, if it exists // Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///"); uuid = stripPrefix(uuid, "extension:///");
if (!this._loaded) if (this._extensionAvailable(uuid))
this._selectExtension(uuid);
else if (!this._loaded)
this._startupUuid = uuid; this._startupUuid = uuid;
else if (!this._showPrefs(uuid)) else
this._skipMainWindow = false; this._skipMainWindow = false;
} }
return 0; return 0;
} }
}); };
var Expander = GObject.registerClass({
Properties: {
'label': GObject.ParamSpec.string(
'label', 'label', 'label',
GObject.ParamFlags.READWRITE,
null
),
},
}, class Expander extends Gtk.Box {
_init(params = {}) {
this._labelText = null;
super._init(Object.assign(params, {
orientation: Gtk.Orientation.VERTICAL,
spacing: 0,
}));
this._frame = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
hexpand: true,
});
let eventBox = new Gtk.EventBox();
this._frame.add(eventBox);
let hbox = new Gtk.Box({
spacing: 6,
margin: 12,
});
eventBox.add(hbox);
this._arrow = new Gtk.Image({
icon_name: 'pan-end-symbolic',
});
hbox.add(this._arrow);
this._label = new Gtk.Label({ label: this._labelText });
hbox.add(this._label);
this._revealer = new Gtk.Revealer();
this._childBin = new Gtk.Frame({
shadow_type: Gtk.ShadowType.IN,
});
this._revealer.add(this._childBin);
// Directly chain up to parent for internal children
super.add(this._frame);
super.add(this._revealer);
let provider = new Gtk.CssProvider();
provider.load_from_data('* { border-top-width: 0; }');
this._childBin.get_style_context().add_provider(
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
);
this._gesture = new Gtk.GestureMultiPress({
widget: this._frame,
button: 0,
exclusive: true,
});
this._gesture.connect('released', (gesture, nPress) => {
if (nPress == 1)
this._revealer.reveal_child = !this._revealer.reveal_child;
});
this._revealer.connect('notify::reveal-child', () => {
if (this._revealer.reveal_child)
this._arrow.icon_name = 'pan-down-symbolic';
else
this._arrow.icon_name = 'pan-end-symbolic';
});
}
get label() {
return this._labelText;
}
set label(text) {
if (this._labelText == text)
return;
if (this._label)
this._label.label = text;
this._labelText = text;
this.notify('label');
}
add(child) {
// set expanded child
this._childBin.get_children().forEach(c => {
this._childBin.remove(c);
});
if (child)
this._childBin.add(child);
}
});
var EmptyPlaceholder = GObject.registerClass(
class EmptyPlaceholder extends Gtk.Box {
_init() {
super._init({
orientation: Gtk.Orientation.VERTICAL,
spacing: 6,
margin: 32,
});
let image = new Gtk.Image({
icon_name: 'application-x-addon-symbolic',
pixel_size: 96,
visible: true,
vexpand: true,
valign: Gtk.Align.END,
});
image.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(image);
let label = new Gtk.Label({
label: `<b><span size="x-large">${_("No Extensions Installed")}</span></b>`,
use_markup: true,
visible: true,
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
let appInfo = Gio.DesktopAppInfo.new('org.gnome.Software.desktop');
let desc = new Gtk.Label({
label: _("Extensions can be installed through Software or <a href=\"https://extensions.gnome.org\">extensions.gnome.org</a>."),
use_markup: true,
wrap: true,
justify: Gtk.Justification.CENTER,
visible: true,
max_width_chars: 50,
hexpand: true,
vexpand: appInfo == null,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
});
this.add(desc);
if (appInfo) {
let button = new Gtk.Button({
label: _("Browse in Software"),
image: new Gtk.Image({
icon_name: "org.gnome.Software-symbolic",
}),
always_show_image: true,
margin_top: 12,
visible: true,
halign: Gtk.Align.CENTER,
valign: Gtk.Align.START,
vexpand: true,
});
this.add(button);
button.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
appInfo.launch([], context);
});
}
}
});
var NoShellPlaceholder = GObject.registerClass(
class NoShellPlaceholder extends Gtk.Box {
_init() {
super._init({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60,
});
let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(
_("Somethings gone wrong")),
use_markup: true,
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again."),
justify: Gtk.Justification.CENTER,
wrap: true,
});
this.add(label);
this.show_all();
}
});
var DescriptionLabel = GObject.registerClass( var DescriptionLabel = GObject.registerClass(
class DescriptionLabel extends Gtk.Label { class DescriptionLabel extends Gtk.Label {
@@ -552,59 +251,30 @@ class DescriptionLabel extends Gtk.Label {
var ExtensionRow = GObject.registerClass( var ExtensionRow = GObject.registerClass(
class ExtensionRow extends Gtk.ListBoxRow { class ExtensionRow extends Gtk.ListBoxRow {
_init(extension) { _init(uuid) {
super._init(); super._init();
this._app = Gio.Application.get_default(); this.uuid = uuid;
this._extension = extension;
this._prefsModule = null;
this.connect('destroy', this._onDestroy.bind(this)); this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.connect('changed::enabled-extensions', () => {
this._switch.state = this._isEnabled();
});
this._settings.connect('changed::disable-extension-version-validation',
() => {
this._switch.sensitive = this._canEnable();
});
this._settings.connect('changed::disable-user-extensions',
() => {
this._switch.sensitive = this._canEnable();
});
this._buildUI(); this._buildUI();
this._extensionStateChangedId = this._app.shellProxy.connectSignal(
'ExtensionStateChanged', (p, sender, [uuid, newState]) => {
if (this.uuid !== uuid)
return;
this._extension = ExtensionUtils.deserializeExtension(newState);
let state = this._extension.state == ExtensionState.ENABLED;
this._switch.block_signal_handler(this._notifyActiveId);
this._switch.state = state;
this._switch.unblock_signal_handler(this._notifyActiveId);
this._switch.sensitive = this._canToggle();
});
}
get uuid() {
return this._extension.uuid;
}
get name() {
return this._extension.metadata.name;
}
get hasPrefs() {
return this._extension.hasPrefs;
}
get url() {
return this._extension.metadata.url;
}
_onDestroy() {
if (!this._app.shellProxy)
return;
if (this._extensionStateChangedId)
this._app.shellProxy.disconnectSignal(this._extensionStateChangedId);
this._extensionStateChangedId = 0;
} }
_buildUI() { _buildUI() {
let extension = ExtensionUtils.extensions[this.uuid];
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin_end: 24, spacing: 24, hexpand: true, margin_end: 24, spacing: 24,
margin: 12 }); margin: 12 });
@@ -614,22 +284,21 @@ class ExtensionRow extends Gtk.ListBoxRow {
spacing: 6, hexpand: true }); spacing: 6, hexpand: true });
hbox.add(vbox); hbox.add(vbox);
let name = GLib.markup_escape_text(this.name, -1); let name = GLib.markup_escape_text(extension.metadata.name, -1);
let label = new Gtk.Label({ label: '<b>' + name + '</b>', let label = new Gtk.Label({ label: '<b>' + name + '</b>',
use_markup: true, use_markup: true,
halign: Gtk.Align.START }); halign: Gtk.Align.START });
vbox.add(label); vbox.add(label);
let desc = this._extension.metadata.description.split('\n')[0]; let desc = extension.metadata.description.split('\n')[0];
label = new DescriptionLabel({ label: desc, wrap: true, lines: 2, label = new DescriptionLabel({ label: desc, wrap: true, lines: 2,
ellipsize: Pango.EllipsizeMode.END, ellipsize: Pango.EllipsizeMode.END,
xalign: 0, yalign: 0 }); xalign: 0, yalign: 0 });
vbox.add(label); vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER, let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
visible: this.hasPrefs,
no_show_all: true }); no_show_all: true });
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic', button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON, icon_size: Gtk.IconSize.BUTTON,
visible: true })); visible: true }));
button.get_style_context().add_class('circular'); button.get_style_context().add_class('circular');
@@ -637,37 +306,51 @@ class ExtensionRow extends Gtk.ListBoxRow {
this.prefsButton = button; this.prefsButton = button;
this._switch = new Gtk.Switch({ this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER, sensitive: this._canEnable(),
sensitive: this._canToggle(), state: this._isEnabled() });
state: this._extension.state === ExtensionState.ENABLED, this._switch.connect('notify::active', () => {
});
this._notifyActiveId = this._switch.connect('notify::active', () => {
if (this._switch.active) if (this._switch.active)
this._app.shellProxy.EnableExtensionRemote(this.uuid); this._enable();
else else
this._app.shellProxy.DisableExtensionRemote(this.uuid); this._disable();
}); });
this._switch.connect('state-set', () => true); this._switch.connect('state-set', () => true);
hbox.add(this._switch); hbox.add(this._switch);
} }
_canToggle() { _canEnable() {
return this._extension.canChange; let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
return !this._settings.get_boolean('disable-user-extensions') &&
!(checkVersion && ExtensionUtils.isOutOfDate(extension));
} }
get prefsModule() { _isEnabled() {
// give extension prefs access to their own extension object let extensions = this._settings.get_strv('enabled-extensions');
ExtensionUtils.getCurrentExtension = () => this._extension; return extensions.indexOf(this.uuid) != -1;
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
} }
return this._prefsModule; _enable() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.indexOf(this.uuid) != -1)
return;
extensions.push(this.uuid);
this._settings.set_strv('enabled-extensions', extensions);
}
_disable() {
let extensions = this._settings.get_strv('enabled-extensions');
let pos = extensions.indexOf(this.uuid);
if (pos == -1)
return;
do {
extensions.splice(pos, 1);
pos = extensions.indexOf(this.uuid);
} while (pos != -1);
this._settings.set_strv('enabled-extensions', extensions);
} }
}); });
@@ -675,15 +358,15 @@ function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities // Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on. // that ExtensionUtils depends on.
window.global = { window.global = {
log(...args) { log() {
print(args.join(', ')); print([].join.call(arguments, ', '));
}, },
logError(s) { logError(s) {
log(`ERROR: ${s}`); log('ERROR: ' + s);
}, },
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell']), userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
}; };
String.prototype.format = Format.format; String.prototype.format = Format.format;
@@ -695,5 +378,6 @@ function main(argv) {
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR); Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
Gettext.textdomain(Config.GETTEXT_PACKAGE); Gettext.textdomain(Config.GETTEXT_PACKAGE);
new Application().run(argv); let app = new Application();
app.application.run(argv);
} }

View File

@@ -1,58 +1,44 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AuthPrompt */
const { Clutter, GObject, Pango, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Pango = imports.gi.Pango;
const Signals = imports.signals;
const St = imports.gi.St;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util; const GdmUtil = imports.gdm.util;
const Util = imports.misc.util;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
var DEFAULT_BUTTON_WELL_ICON_SIZE = 16; var DEFAULT_BUTTON_WELL_ICON_SIZE = 16;
var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000; var DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1.0;
var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300; var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 0.3;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500; var MESSAGE_FADE_OUT_ANIMATION_TIME = 0.5;
const WIGGLE_OFFSET = 6;
const WIGGLE_DURATION = 65;
const N_WIGGLES = 3;
var AuthPromptMode = { var AuthPromptMode = {
UNLOCK_ONLY: 0, UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1, UNLOCK_OR_LOG_IN: 1
}; };
var AuthPromptStatus = { var AuthPromptStatus = {
NOT_VERIFYING: 0, NOT_VERIFYING: 0,
VERIFYING: 1, VERIFYING: 1,
VERIFICATION_FAILED: 2, VERIFICATION_FAILED: 2,
VERIFICATION_SUCCEEDED: 3, VERIFICATION_SUCCEEDED: 3
}; };
var BeginRequestType = { var BeginRequestType = {
PROVIDE_USERNAME: 0, PROVIDE_USERNAME: 0,
DONT_PROVIDE_USERNAME: 1, DONT_PROVIDE_USERNAME: 1
}; };
var AuthPrompt = GObject.registerClass({ var AuthPrompt = class {
Signals: { constructor(gdmClient, mode) {
'cancelled': {},
'failed': {},
'next': {},
'prompted': {},
'reset': { param_types: [GObject.TYPE_UINT] },
},
}, class AuthPrompt extends St.BoxLayout {
_init(gdmClient, mode) {
super._init({
style_class: 'login-dialog-prompt-layout',
vertical: true,
});
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient; this._gdmClient = gdmClient;
@@ -64,7 +50,7 @@ var AuthPrompt = GObject.registerClass({
else if (this._mode == AuthPromptMode.UNLOCK_OR_LOG_IN) else if (this._mode == AuthPromptMode.UNLOCK_OR_LOG_IN)
reauthenticationOnly = false; reauthenticationOnly = false;
this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly }); this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly: reauthenticationOnly });
this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this)); this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this));
this._userVerifier.connect('show-message', this._onShowMessage.bind(this)); this._userVerifier.connect('show-message', this._onShowMessage.bind(this));
@@ -78,68 +64,70 @@ var AuthPrompt = GObject.registerClass({
this.connect('next', () => { this.connect('next', () => {
this.updateSensitivity(false); this.updateSensitivity(false);
this.startSpinning(); this.startSpinning();
if (this._queryingService) if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text); this._userVerifier.answerQuery(this._queryingService, this._entry.text);
else } else {
this._preemptiveAnswer = this._entry.text; this._preemptiveAnswer = this._entry.text;
}
}); });
this.connect('destroy', this._onDestroy.bind(this)); this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
this._userWell = new St.Bin({ this.actor.connect('destroy', this._onDestroy.bind(this));
x_expand: true, this.actor.connect('key-press-event', (actor, event) => {
y_expand: true, if (event.get_key_symbol() == Clutter.KEY_Escape)
}); this.cancel();
this.add_child(this._userWell); return Clutter.EVENT_PROPAGATE;
this._label = new St.Label({
style_class: 'login-dialog-prompt-label',
x_expand: false,
y_expand: true,
}); });
this.add_child(this._label); this._userWell = new St.Bin({ x_fill: true,
this._entry = new St.Entry({ x_align: St.Align.START });
style_class: 'login-dialog-prompt-entry', this.actor.add(this._userWell,
can_focus: true, { x_align: St.Align.START,
x_expand: false, x_fill: true,
y_expand: true, y_fill: true,
}); expand: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE }); this._label = new St.Label({ style_class: 'login-dialog-prompt-label' });
this.add_child(this._entry); this.actor.add(this._label,
{ expand: true,
x_fill: false,
y_fill: true,
x_align: St.Align.START });
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true });
this.actor.add(this._entry,
{ expand: true,
x_fill: true,
y_fill: false,
x_align: St.Align.START });
this._entry.grab_key_focus(); this._entry.grab_key_focus();
this._message = new St.Label({ this._message = new St.Label({ opacity: 0,
opacity: 0, styleClass: 'login-dialog-message' });
styleClass: 'login-dialog-message',
x_expand: false,
y_expand: true,
y_align: Clutter.ActorAlign.START,
});
this._message.clutter_text.line_wrap = true; this._message.clutter_text.line_wrap = true;
this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.add_child(this._message); this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
this._buttonBox = new St.BoxLayout({ this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
style_class: 'login-dialog-button-box', vertical: false });
vertical: false, this.actor.add(this._buttonBox,
y_align: Clutter.ActorAlign.END, { expand: true,
}); x_align: St.Align.MIDDLE,
this.add_child(this._buttonBox); y_align: St.Align.END });
this._defaultButtonWell = new St.Widget({ this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
layout_manager: new Clutter.BinLayout(), this._defaultButtonWellActor = null;
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
this._initButtons(); this._initButtons();
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE); this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.opacity = 0; this._spinner.actor.opacity = 0;
this._spinner.show(); this._spinner.actor.show();
this._defaultButtonWell.add_child(this._spinner); this._defaultButtonWell.add_child(this._spinner.actor);
} }
_onDestroy() { _onDestroy() {
@@ -147,39 +135,39 @@ var AuthPrompt = GObject.registerClass({
this._userVerifier = null; this._userVerifier = null;
} }
vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
}
_initButtons() { _initButtons() {
this.cancelButton = new St.Button({ this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true, reactive: true,
can_focus: true, can_focus: true,
label: _("Cancel"), label: _("Cancel") });
x_expand: true, this.cancelButton.connect('clicked', () => { this.cancel(); });
x_align: Clutter.ActorAlign.START, this._buttonBox.add(this.cancelButton,
y_align: Clutter.ActorAlign.END, { expand: false,
}); x_fill: false,
this.cancelButton.connect('clicked', () => this.cancel()); y_fill: false,
this._buttonBox.add_child(this.cancelButton); x_align: St.Align.START,
y_align: St.Align.END });
this._buttonBox.add_child(this._defaultButtonWell); this._buttonBox.add(this._defaultButtonWell,
this.nextButton = new St.Button({ { expand: true,
style_class: 'modal-dialog-button button', x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this.nextButton = new St.Button({ style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true, reactive: true,
can_focus: true, can_focus: true,
label: _("Next"), label: _("Next") });
x_align: Clutter.ActorAlign.END, this.nextButton.connect('clicked', () => { this.emit('next'); });
y_align: Clutter.ActorAlign.END,
});
this.nextButton.connect('clicked', () => this.emit('next'));
this.nextButton.add_style_pseudo_class('default'); this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add_child(this.nextButton); this._buttonBox.add(this.nextButton,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.END });
this._updateNextButtonSensitivity(this._entry.text.length > 0); this._updateNextButtonSensitivity(this._entry.text.length > 0);
@@ -257,12 +245,6 @@ var AuthPrompt = GObject.registerClass({
this.updateSensitivity(canRetry); this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
Util.wiggle(this._entry, {
offset: WIGGLE_OFFSET,
duration: WIGGLE_DURATION,
wiggleCount: N_WIGGLES,
});
} }
_onVerificationComplete() { _onVerificationComplete() {
@@ -288,16 +270,16 @@ var AuthPrompt = GObject.registerClass({
let oldActor = this._defaultButtonWellActor; let oldActor = this._defaultButtonWellActor;
if (oldActor) if (oldActor)
oldActor.remove_all_transitions(); Tweener.removeTweens(oldActor);
let wasSpinner; let wasSpinner;
if (oldActor == this._spinner) if (oldActor == this._spinner.actor)
wasSpinner = true; wasSpinner = true;
else else
wasSpinner = false; wasSpinner = false;
let isSpinner; let isSpinner;
if (actor == this._spinner) if (actor == this._spinner.actor)
isSpinner = true; isSpinner = true;
else else
isSpinner = false; isSpinner = false;
@@ -311,17 +293,18 @@ var AuthPrompt = GObject.registerClass({
this._spinner.stop(); this._spinner.stop();
} }
} else { } else {
oldActor.ease({ Tweener.addTween(oldActor,
opacity: 0, { opacity: 0,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear',
onComplete: () => { onCompleteScope: this,
onComplete() {
if (wasSpinner) { if (wasSpinner) {
if (this._spinner) if (this._spinner)
this._spinner.stop(); this._spinner.stop();
} }
}, }
}); });
} }
} }
@@ -330,23 +313,21 @@ var AuthPrompt = GObject.registerClass({
if (isSpinner) if (isSpinner)
this._spinner.play(); this._spinner.play();
if (!animate) { if (!animate)
actor.opacity = 255; actor.opacity = 255;
} else { else
actor.ease({ Tweener.addTween(actor,
opacity: 255, { opacity: 255,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear' });
});
}
} }
this._defaultButtonWellActor = actor; this._defaultButtonWellActor = actor;
} }
startSpinning() { startSpinning() {
this.setActorInDefaultButtonWell(this._spinner, true); this.setActorInDefaultButtonWell(this._spinner.actor, true);
} }
stopSpinning() { stopSpinning() {
@@ -388,11 +369,11 @@ var AuthPrompt = GObject.registerClass({
_fadeOutMessage() { _fadeOutMessage() {
if (this._message.opacity == 0) if (this._message.opacity == 0)
return; return;
this._message.remove_all_transitions(); Tweener.removeTweens(this._message);
this._message.ease({ Tweener.addTween(this._message,
opacity: 0, { opacity: 0,
duration: MESSAGE_FADE_OUT_ANIMATION_TIME, time: MESSAGE_FADE_OUT_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad'
}); });
} }
@@ -408,7 +389,7 @@ var AuthPrompt = GObject.registerClass({
this._message.remove_style_class_name('login-dialog-message-hint'); this._message.remove_style_class_name('login-dialog-message-hint');
if (message) { if (message) {
this._message.remove_all_transitions(); Tweener.removeTweens(this._message);
this._message.text = message; this._message.text = message;
this._message.opacity = 255; this._message.opacity = 255;
} else { } else {
@@ -427,9 +408,9 @@ var AuthPrompt = GObject.registerClass({
this._entry.clutter_text.editable = sensitive; this._entry.clutter_text.editable = sensitive;
} }
vfunc_hide() { hide() {
this.setActorInDefaultButtonWell(null, true); this.setActorInDefaultButtonWell(null, true);
super.vfunc_hide(); this.actor.hide();
this._message.opacity = 0; this._message.opacity = 0;
this.setUser(null); this.setUser(null);
@@ -445,8 +426,7 @@ var AuthPrompt = GObject.registerClass({
if (user) { if (user) {
let userWidget = new UserWidget.UserWidget(user); let userWidget = new UserWidget.UserWidget(user);
userWidget.x_align = Clutter.ActorAlign.START; this._userWell.set_child(userWidget.actor);
this._userWell.set_child(userWidget);
} }
} }
@@ -525,10 +505,11 @@ var AuthPrompt = GObject.registerClass({
} }
cancel() { cancel() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
return; return;
}
this.reset(); this.reset();
this.emit('cancelled'); this.emit('cancelled');
} }
}); };
Signals.addSignalMethods(AuthPrompt.prototype);

View File

@@ -20,7 +20,7 @@
* In order for transformation animations to look good, they need to be * In order for transformation animations to look good, they need to be
* incremental and have some order to them (e.g., fade out hidden items, * incremental and have some order to them (e.g., fade out hidden items,
* then shrink to close the void left over). Chaining animations in this way can * then shrink to close the void left over). Chaining animations in this way can
* be error-prone and wordy using just ease() callbacks. * be error-prone and wordy using just Tweener callbacks.
* *
* The classes in this file help with this: * The classes in this file help with this:
* *
@@ -44,7 +44,6 @@
* replaced by something else. * replaced by something else.
*/ */
const { GObject } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
var Task = class { var Task = class {
@@ -112,24 +111,26 @@ var Batch = class extends Task {
for (let i = 0; i < tasks.length; i++) { for (let i = 0; i < tasks.length; i++) {
let task; let task;
if (tasks[i] instanceof Task) if (tasks[i] instanceof Task) {
task = tasks[i]; task = tasks[i];
else if (typeof tasks[i] == 'function') } else if (typeof tasks[i] == 'function') {
task = new Task(scope, tasks[i]); task = new Task(scope, tasks[i]);
else } else {
throw new Error('Batch tasks must be functions or Task, Hold or Batch objects'); throw new Error('Batch tasks must be functions or Task, Hold or Batch objects');
}
this.tasks.push(task); this.tasks.push(task);
} }
} }
process() { process() {
throw new GObject.NotImplementedError(`process in ${this.constructor.name}`); throw new Error('Not implemented');
} }
runTask() { runTask() {
if (!(this._currentTaskIndex in this.tasks)) if (!(this._currentTaskIndex in this.tasks)) {
return null; return null;
}
return this.tasks[this._currentTaskIndex].run(); return this.tasks[this._currentTaskIndex].run();
} }
@@ -177,8 +178,9 @@ var ConcurrentBatch = class extends Batch {
process() { process() {
let hold = this.runTask(); let hold = this.runTask();
if (hold) if (hold) {
this.hold.acquireUntilAfter(hold); this.hold.acquireUntilAfter(hold);
}
// Regardless of the state of the just run task, // Regardless of the state of the just run task,
// fire off the next one, so all the tasks can run // fire off the next one, so all the tasks can run
@@ -199,6 +201,7 @@ var ConsecutiveBatch = class extends Batch {
hold.disconnect(signalId); hold.disconnect(signalId);
this.nextTask(); this.nextTask();
}); });
return;
} else { } else {
// This task finished, process the next one // This task finished, process the next one
this.nextTask(); this.nextTask();

View File

@@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported FprintManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = ` const FprintManagerIface = `
<node> <node>
@@ -20,12 +21,12 @@ function FprintManager() {
g_interface_info: FprintManagerInfo, g_interface_info: FprintManagerInfo,
g_name: 'net.reactivated.Fprint', g_name: 'net.reactivated.Fprint',
g_object_path: '/net/reactivated/Fprint/Manager', g_object_path: '/net/reactivated/Fprint/Manager',
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES }); g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
try { try {
self.init(null); self.init(null);
} catch (e) { } catch(e) {
log(`Failed to connect to Fprint service: ${e.message}`); log('Failed to connect to Fprint service: ' + e.message);
return null; return null;
} }

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LoginDialog */
/* /*
* Copyright 2011 Red Hat, Inc * Copyright 2011 Red Hat, Inc
* *
@@ -17,8 +16,19 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
const { AccountsService, Atk, Clutter, Gdm, Gio, const AccountsService = imports.gi.AccountsService;
GLib, GObject, Meta, Pango, Shell, St } = imports.gi; const Atk = imports.gi.Atk;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const AuthPrompt = imports.gdm.authPrompt; const AuthPrompt = imports.gdm.authPrompt;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
@@ -30,44 +40,45 @@ const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main; const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Realmd = imports.gdm.realmd; const Realmd = imports.gdm.realmd;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
const _FADE_ANIMATION_TIME = 250; const _FADE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 500; const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48; const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5; const _MAX_BOTTOM_MENU_ITEMS = 5;
var UserListItem = GObject.registerClass({ var UserListItem = class {
Signals: { 'activate': {} }, constructor(user) {
}, class UserListItem extends St.Button {
_init(user) {
let layout = new St.BoxLayout({
vertical: true,
x_align: Clutter.ActorAlign.START,
});
super._init({
style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
x_expand: true,
child: layout,
reactive: true,
});
this.user = user; this.user = user;
this._userChangedId = this.user.connect('changed', this._userChangedId = this.user.connect('changed',
this._onUserChanged.bind(this)); this._onUserChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this)); let layout = new St.BoxLayout({ vertical: true });
this.connect('notify::hover', () => { this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
this._setSelected(this.hover); button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true,
child: layout,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('key-focus-in', () => {
this._setSelected(true);
});
this.actor.connect('key-focus-out', () => {
this._setSelected(false);
});
this.actor.connect('notify::hover', () => {
this._setSelected(this.actor.hover);
}); });
this._userWidget = new UserWidget.UserWidget(this.user); this._userWidget = new UserWidget.UserWidget(this.user);
layout.add(this._userWidget); layout.add(this._userWidget.actor);
this._userWidget.bind_property('label-actor', this, 'label-actor', this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor',
GObject.BindingFlags.SYNC_CREATE); GObject.BindingFlags.SYNC_CREATE);
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
@@ -75,44 +86,35 @@ var UserListItem = GObject.registerClass({
visible: false }); visible: false });
layout.add(this._timedLoginIndicator); layout.add(this._timedLoginIndicator);
this.actor.connect('clicked', this._onClicked.bind(this));
this._onUserChanged(); this._onUserChanged();
} }
vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this._setSelected(true);
}
vfunc_key_focus_out() {
super.vfunc_key_focus_out();
this._setSelected(false);
}
_onUserChanged() { _onUserChanged() {
this._updateLoggedIn(); this._updateLoggedIn();
} }
_updateLoggedIn() { _updateLoggedIn() {
if (this.user.is_logged_in()) if (this.user.is_logged_in())
this.add_style_pseudo_class('logged-in'); this.actor.add_style_pseudo_class('logged-in');
else else
this.remove_style_pseudo_class('logged-in'); this.actor.remove_style_pseudo_class('logged-in');
} }
_onDestroy() { _onDestroy() {
this.user.disconnect(this._userChangedId); this.user.disconnect(this._userChangedId);
} }
vfunc_clicked() { _onClicked() {
this.emit('activate'); this.emit('activate');
} }
_setSelected(selected) { _setSelected(selected) {
if (selected) { if (selected) {
this.add_style_pseudo_class('selected'); this.actor.add_style_pseudo_class('selected');
this.grab_key_focus(); this.actor.grab_key_focus();
} else { } else {
this.remove_style_pseudo_class('selected'); this.actor.remove_style_pseudo_class('selected');
} }
} }
@@ -125,7 +127,7 @@ var UserListItem = GObject.registerClass({
let startTime = GLib.get_monotonic_time(); let startTime = GLib.get_monotonic_time();
this._timedLoginTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 33, this._timedLoginTimeoutId = GLib.timeout_add (GLib.PRIORITY_DEFAULT, 33,
() => { () => {
let currentTime = GLib.get_monotonic_time(); let currentTime = GLib.get_monotonic_time();
let elapsedTime = (currentTime - startTime) / GLib.USEC_PER_SEC; let elapsedTime = (currentTime - startTime) / GLib.USEC_PER_SEC;
@@ -153,33 +155,23 @@ var UserListItem = GObject.registerClass({
this._timedLoginIndicator.visible = false; this._timedLoginIndicator.visible = false;
this._timedLoginIndicator.scale_x = 0.; this._timedLoginIndicator.scale_x = 0.;
} }
}); };
Signals.addSignalMethods(UserListItem.prototype);
var UserList = GObject.registerClass({ var UserList = class {
Signals: { constructor() {
'activate': { param_types: [UserListItem.$gtype] }, this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
'item-added': { param_types: [UserListItem.$gtype] }, this.actor.set_policy(Gtk.PolicyType.NEVER,
}, Gtk.PolicyType.AUTOMATIC);
}, class UserList extends St.ScrollView {
_init() {
super._init({
style_class: 'login-dialog-user-list-view',
x_expand: true,
y_expand: true,
});
this.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC);
this._box = new St.BoxLayout({ vertical: true, this._box = new St.BoxLayout({ vertical: true,
style_class: 'login-dialog-user-list', style_class: 'login-dialog-user-list',
pseudo_class: 'expanded' }); pseudo_class: 'expanded' });
this.add_actor(this._box); this.actor.add_actor(this._box);
this._items = {}; this._items = {};
}
vfunc_key_focus_in() { this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
this._moveFocusToItems();
} }
_moveFocusToItems() { _moveFocusToItems() {
@@ -188,10 +180,10 @@ var UserList = GObject.registerClass({
if (!hasItems) if (!hasItems)
return; return;
if (global.stage.get_key_focus() != this) if (global.stage.get_key_focus() != this.actor)
return; return;
let focusSet = this.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); let focusSet = this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
if (!focusSet) { if (!focusSet) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._moveFocusToItems(); this._moveFocusToItems();
@@ -205,6 +197,8 @@ var UserList = GObject.registerClass({
} }
updateStyle(isExpanded) { updateStyle(isExpanded) {
let tasks = [];
if (isExpanded) if (isExpanded)
this._box.add_style_pseudo_class('expanded'); this._box.add_style_pseudo_class('expanded');
else else
@@ -212,26 +206,27 @@ var UserList = GObject.registerClass({
for (let userName in this._items) { for (let userName in this._items) {
let item = this._items[userName]; let item = this._items[userName];
item.sync_hover(); item.actor.sync_hover();
} }
} }
scrollToItem(item) { scrollToItem(item) {
let box = item.get_allocation_box(); let box = item.actor.get_allocation_box();
let adjustment = this.get_vscroll_bar().get_adjustment(); let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
adjustment.ease(value, { Tweener.removeTweens(adjustment);
mode: Clutter.AnimationMode.EASE_OUT_QUAD, Tweener.addTween (adjustment,
duration: _SCROLL_ANIMATION_TIME, { value: value,
}); time: _SCROLL_ANIMATION_TIME,
transition: 'easeOutQuad' });
} }
jumpToItem(item) { jumpToItem(item) {
let box = item.get_allocation_box(); let box = item.actor.get_allocation_box();
let adjustment = this.get_vscroll_bar().get_adjustment(); let adjustment = this.actor.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
@@ -269,14 +264,14 @@ var UserList = GObject.registerClass({
this.removeUser(user); this.removeUser(user);
let item = new UserListItem(user); let item = new UserListItem(user);
this._box.add_child(item); this._box.add(item.actor, { x_fill: true });
this._items[userName] = item; this._items[userName] = item;
item.connect('activate', this._onItemActivated.bind(this)); item.connect('activate', this._onItemActivated.bind(this));
// Try to keep the focused item front-and-center // Try to keep the focused item front-and-center
item.connect('key-focus-in', () => this.scrollToItem(item)); item.actor.connect('key-focus-in', () => { this.scrollToItem(item); });
this._moveFocusToItems(); this._moveFocusToItems();
@@ -297,37 +292,33 @@ var UserList = GObject.registerClass({
if (!item) if (!item)
return; return;
item.destroy(); item.actor.destroy();
delete this._items[userName]; delete this._items[userName];
} }
numItems() { numItems() {
return Object.keys(this._items).length; return Object.keys(this._items).length;
} }
}); };
Signals.addSignalMethods(UserList.prototype);
var SessionMenuButton = GObject.registerClass({ var SessionMenuButton = class {
Signals: { 'session-activated': { param_types: [GObject.TYPE_STRING] } }, constructor() {
}, class SessionMenuButton extends St.Bin {
_init() {
let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' }); let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
let button = new St.Button({ this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
style_class: 'login-dialog-session-list-button',
reactive: true, reactive: true,
track_hover: true, track_hover: true,
can_focus: true, can_focus: true,
accessible_name: _("Choose Session"), accessible_name: _("Choose Session"),
accessible_role: Atk.Role.MENU, accessible_role: Atk.Role.MENU,
child: gearIcon, child: gearIcon });
});
super._init({ child: button }); this.actor = new St.Bin({ child: this._button });
this._button = button;
let side = St.Side.TOP; let side = St.Side.TOP;
let align = 0; let align = 0;
if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) { if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) {
if (this.text_direction == Clutter.TextDirection.RTL) if (this.actor.text_direction == Clutter.TextDirection.RTL)
side = St.Side.RIGHT; side = St.Side.RIGHT;
else else
side = St.Side.LEFT; side = St.Side.LEFT;
@@ -344,11 +335,10 @@ var SessionMenuButton = GObject.registerClass({
this._button.remove_style_pseudo_class('active'); this._button.remove_style_pseudo_class('active');
}); });
this._manager = new PopupMenu.PopupMenuManager(this._button, this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
{ actionMode: Shell.ActionMode.NONE });
this._manager.addMenu(this._menu); this._manager.addMenu(this._menu);
this._button.connect('clicked', () => this._menu.toggle()); this._button.connect('clicked', () => { this._menu.toggle(); });
this._items = {}; this._items = {};
this._activeSessionId = null; this._activeSessionId = null;
@@ -393,7 +383,7 @@ var SessionMenuButton = GObject.registerClass({
} }
for (let i = 0; i < ids.length; i++) { for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription_] = Gdm.get_session_name_and_description(ids[i]); let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
let id = ids[i]; let id = ids[i];
let item = new PopupMenu.PopupMenuItem(sessionName); let item = new PopupMenu.PopupMenuItem(sessionName);
@@ -406,13 +396,15 @@ var SessionMenuButton = GObject.registerClass({
}); });
} }
} }
}); };
Signals.addSignalMethods(SessionMenuButton.prototype);
var LoginDialog = GObject.registerClass({ var LoginDialog = GObject.registerClass({
Signals: { 'failed': {} }, Signals: { 'failed': {} },
}, class LoginDialog extends St.Widget { }, class LoginDialog extends St.Widget {
_init(parentActor) { _init(parentActor) {
super._init({ style_class: 'login-dialog', visible: false }); super._init({ style_class: 'login-dialog',
visible: false });
this.get_accessible().set_role(Atk.Role.WINDOW); this.get_accessible().set_role(Atk.Role.WINDOW);
@@ -420,18 +412,18 @@ var LoginDialog = GObject.registerClass({
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
parentActor.add_child(this); parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default(); this._userManager = AccountsService.UserManager.get_default()
this._gdmClient = new Gdm.Client(); this._gdmClient = new Gdm.Client();
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA }); this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`, this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
this._updateBanner.bind(this)); this._updateBanner.bind(this));
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`, this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
this._updateBanner.bind(this)); this._updateBanner.bind(this));
this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`, this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
this._updateDisableUserList.bind(this)); this._updateDisableUserList.bind(this));
this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`, this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
this._updateLogo.bind(this)); this._updateLogo.bind(this));
this._textureCache = St.TextureCache.get_default(); this._textureCache = St.TextureCache.get_default();
@@ -446,40 +438,43 @@ var LoginDialog = GObject.registerClass({
this.add_child(this._userSelectionBox); this.add_child(this._userSelectionBox);
this._userList = new UserList(); this._userList = new UserList();
this._userSelectionBox.add_child(this._userList); this._userSelectionBox.add(this._userList.actor,
{ expand: true,
x_fill: true,
y_fill: true });
this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN); this._authPrompt = new AuthPrompt.AuthPrompt(this._gdmClient, AuthPrompt.AuthPromptMode.UNLOCK_OR_LOG_IN);
this._authPrompt.connect('prompted', this._onPrompted.bind(this)); this._authPrompt.connect('prompted', this._onPrompted.bind(this));
this._authPrompt.connect('reset', this._onReset.bind(this)); this._authPrompt.connect('reset', this._onReset.bind(this));
this._authPrompt.hide(); this._authPrompt.hide();
this.add_child(this._authPrompt); this.add_child(this._authPrompt.actor);
// translators: this message is shown below the user list on the // translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for // login screen. It can be activated to reveal an entry for
// manually entering the username. // manually entering the username.
let notListedLabel = new St.Label({ let notListedLabel = new St.Label({ text: _("Not listed?"),
text: _("Not listed?"), style_class: 'login-dialog-not-listed-label' });
style_class: 'login-dialog-not-listed-label', this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
x_align: Clutter.ActorAlign.START,
});
this._notListedButton = new St.Button({
style_class: 'login-dialog-not-listed-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true, can_focus: true,
child: notListedLabel, child: notListedLabel,
reactive: true, reactive: true,
}); x_align: St.Align.START,
x_fill: true });
this._notListedButton.connect('clicked', this._hideUserListAskForUsernameAndBeginVerification.bind(this)); this._notListedButton.connect('clicked', this._hideUserListAskForUsernameAndBeginVerification.bind(this));
this._notListedButton.hide(); this._notListedButton.hide();
this._userSelectionBox.add_child(this._notListedButton); this._userSelectionBox.add(this._notListedButton,
{ expand: false,
x_align: St.Align.START,
x_fill: true });
this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view', this._bannerView = new St.ScrollView({ style_class: 'login-dialog-banner-view',
opacity: 0, opacity: 0,
vscrollbar_policy: St.PolicyType.AUTOMATIC, vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: St.PolicyType.NEVER }); hscrollbar_policy: Gtk.PolicyType.NEVER });
this.add_child(this._bannerView); this.add_child(this._bannerView);
let bannerBox = new St.BoxLayout({ vertical: true }); let bannerBox = new St.BoxLayout({ vertical: true });
@@ -495,9 +490,6 @@ var LoginDialog = GObject.registerClass({
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin', this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END }); y_align: Clutter.ActorAlign.END });
this._logoBin.connect('resource-scale-changed', () => {
this._updateLogoTexture(this._textureCache, this._logoFile);
});
this.add_child(this._logoBin); this.add_child(this._logoBin);
this._updateLogo(); this._updateLogo();
@@ -509,11 +501,11 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton = new SessionMenuButton(); this._sessionMenuButton = new SessionMenuButton();
this._sessionMenuButton.connect('session-activated', this._sessionMenuButton.connect('session-activated',
(list, sessionId) => { (list, sessionId) => {
this._greeter.call_select_session_sync(sessionId, null); this._greeter.call_select_session_sync (sessionId, null);
}); });
this._sessionMenuButton.opacity = 0; this._sessionMenuButton.actor.opacity = 0;
this._sessionMenuButton.show(); this._sessionMenuButton.actor.show();
this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton); this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor);
this._disableUserList = undefined; this._disableUserList = undefined;
this._userListLoaded = false; this._userListLoaded = false;
@@ -534,7 +526,7 @@ var LoginDialog = GObject.registerClass({
_getBannerAllocation(dialogBox) { _getBannerAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
let [, , natWidth, natHeight] = this._bannerView.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2); actorBox.x1 = Math.floor(centerX - natWidth / 2);
@@ -548,7 +540,7 @@ var LoginDialog = GObject.registerClass({
_getLogoBinAllocation(dialogBox) { _getLogoBinAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
let [, , natWidth, natHeight] = this._logoBin.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2); actorBox.x1 = Math.floor(centerX - natWidth / 2);
@@ -562,7 +554,7 @@ var LoginDialog = GObject.registerClass({
_getCenterActorAllocation(dialogBox, actor) { _getCenterActorAllocation(dialogBox, actor) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
let [, , natWidth, natHeight] = actor.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2; let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2; let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
@@ -589,15 +581,19 @@ var LoginDialog = GObject.registerClass({
// First find out what space the children require // First find out what space the children require
let bannerAllocation = null; let bannerAllocation = null;
let bannerHeight = 0; let bannerHeight = 0;
let bannerWidth = 0;
if (this._bannerView.visible) { if (this._bannerView.visible) {
bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView); bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1; bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
} }
let authPromptAllocation = null; let authPromptAllocation = null;
let authPromptHeight = 0;
let authPromptWidth = 0; let authPromptWidth = 0;
if (this._authPrompt.visible) { if (this._authPrompt.actor.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt); authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1; authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
} }
@@ -662,9 +658,9 @@ var LoginDialog = GObject.registerClass({
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2); bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth); bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
// figure out how tall it would like to be and try to accommodate // figure out how tall it would like to be and try to accomodate
// but don't let it get too close to the logo // but don't let it get too close to the logo
let [, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth); let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
let maxWideHeight = dialogHeight - 3 * logoHeight; let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight); wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
@@ -702,11 +698,12 @@ var LoginDialog = GObject.registerClass({
} }
// Finally hand out the allocations // Finally hand out the allocations
if (bannerAllocation) if (bannerAllocation) {
this._bannerView.allocate(bannerAllocation, flags); this._bannerView.allocate(bannerAllocation, flags);
}
if (authPromptAllocation) if (authPromptAllocation)
this._authPrompt.allocate(authPromptAllocation, flags); this._authPrompt.actor.allocate(authPromptAllocation, flags);
if (userSelectionAllocation) if (userSelectionAllocation)
this._userSelectionBox.allocate(userSelectionAllocation, flags); this._userSelectionBox.allocate(userSelectionAllocation, flags);
@@ -773,15 +770,14 @@ var LoginDialog = GObject.registerClass({
_fadeInBannerView() { _fadeInBannerView() {
this._bannerView.show(); this._bannerView.show();
this._bannerView.ease({ Tweener.addTween(this._bannerView,
opacity: 255, { opacity: 255,
duration: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad' });
});
} }
_hideBannerView() { _hideBannerView() {
this._bannerView.remove_all_transitions(); Tweener.removeTweens(this._bannerView);
this._bannerView.opacity = 0; this._bannerView.opacity = 0;
this._bannerView.hide(); this._bannerView.hide();
} }
@@ -791,12 +787,11 @@ var LoginDialog = GObject.registerClass({
return; return;
this._logoBin.destroy_all_children(); this._logoBin.destroy_all_children();
if (this._logoFile && this._logoBin.resource_scale > 0) { if (this._logoFile) {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile, this._logoBin.add_child(this._textureCache.load_file_async(this._logoFile,
-1, _LOGO_ICON_HEIGHT, -1, _LOGO_ICON_HEIGHT,
scaleFactor, scaleFactor));
this._logoBin.resource_scale));
} }
} }
@@ -810,7 +805,7 @@ var LoginDialog = GObject.registerClass({
_onPrompted() { _onPrompted() {
if (this._shouldShowSessionMenuButton()) { if (this._shouldShowSessionMenuButton()) {
this._sessionMenuButton.updateSensitivity(true); this._sessionMenuButton.updateSensitivity(true);
this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton); this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor);
} else { } else {
this._sessionMenuButton.updateSensitivity(false); this._sessionMenuButton.updateSensitivity(false);
} }
@@ -819,9 +814,9 @@ var LoginDialog = GObject.registerClass({
_resetGreeterProxy() { _resetGreeterProxy() {
if (GLib.getenv('GDM_GREETER_TEST') != '1') { if (GLib.getenv('GDM_GREETER_TEST') != '1') {
if (this._greeter) if (this._greeter) {
this._greeter.run_dispose(); this._greeter.run_dispose();
}
this._greeter = this._gdmClient.get_greeter_sync(null); this._greeter = this._gdmClient.get_greeter_sync(null);
this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed', this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed',
@@ -870,15 +865,14 @@ var LoginDialog = GObject.registerClass({
} }
_showPrompt() { _showPrompt() {
if (this._authPrompt.visible) if (this._authPrompt.actor.visible)
return; return;
this._authPrompt.opacity = 0; this._authPrompt.actor.opacity = 0;
this._authPrompt.show(); this._authPrompt.actor.show();
this._authPrompt.ease({ Tweener.addTween(this._authPrompt.actor,
opacity: 255, { opacity: 255,
duration: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad' });
});
this._fadeInBannerView(); this._fadeInBannerView();
} }
@@ -922,31 +916,28 @@ var LoginDialog = GObject.registerClass({
this._showPrompt(); this._showPrompt();
} }
_bindOpacity() {
this._bindings = Main.layoutManager.uiGroup.get_children()
.filter(c => c != Main.layoutManager.screenShieldGroup)
.map(c => this.bind_property('opacity', c, 'opacity', 0));
}
_unbindOpacity() {
this._bindings.forEach(b => b.unbind());
}
_loginScreenSessionActivated() { _loginScreenSessionActivated() {
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
return; return;
this._bindOpacity(); Tweener.addTween(this,
this.ease({ { opacity: 255,
opacity: 255, time: _FADE_ANIMATION_TIME,
duration: _FADE_ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onUpdate() {
onComplete: () => { let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
onComplete() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING) if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset(); this._authPrompt.reset();
this._unbindOpacity();
}, },
}); onCompleteScope: this });
} }
_gotGreeterSessionProxy(proxy) { _gotGreeterSessionProxy(proxy) {
@@ -959,20 +950,27 @@ var LoginDialog = GObject.registerClass({
} }
_startSession(serviceName) { _startSession(serviceName) {
this._bindOpacity(); Tweener.addTween(this,
this.ease({ { opacity: 0,
opacity: 0, time: _FADE_ANIMATION_TIME,
duration: _FADE_ANIMATION_TIME, transition: 'easeOutQuad',
mode: Clutter.AnimationMode.EASE_OUT_QUAD, onUpdate() {
onComplete: () => { let children = Main.layoutManager.uiGroup.get_children();
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
this._unbindOpacity(); for (let i = 0; i < children.length; i++) {
if (children[i] != Main.layoutManager.screenShieldGroup)
children[i].opacity = this.opacity;
}
}, },
}); onUpdateScope: this,
onComplete() {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
},
onCompleteScope: this });
} }
_onSessionOpened(client, serviceName) { _onSessionOpened(client, serviceName) {
this._authPrompt.finish(() => this._startSession(serviceName)); this._authPrompt.finish(() => { this._startSession(serviceName); });
} }
_waitForItemForUser(userName) { _waitForItemForUser(userName) {
@@ -984,13 +982,13 @@ var LoginDialog = GObject.registerClass({
let hold = new Batch.Hold(); let hold = new Batch.Hold();
let signalId = this._userList.connect('item-added', let signalId = this._userList.connect('item-added',
() => { () => {
item = this._userList.getItemFromUserName(userName); let item = this._userList.getItemFromUserName(userName);
if (item) if (item)
hold.release(); hold.release();
}); });
hold.connect('release', () => this._userList.disconnect(signalId)); hold.connect('release', () => { this._userList.disconnect(signalId); });
return hold; return hold;
} }
@@ -1038,8 +1036,9 @@ var LoginDialog = GObject.registerClass({
() => { () => {
// If we're just starting out, start on the right item. // If we're just starting out, start on the right item.
if (!this._userManager.is_loaded) if (!this._userManager.is_loaded) {
this._userList.jumpToItem(loginItem); this._userList.jumpToItem(loginItem);
}
}, },
() => { () => {
@@ -1053,19 +1052,18 @@ var LoginDialog = GObject.registerClass({
return this._blockTimedLoginUntilIdle(); return this._blockTimedLoginUntilIdle();
} else { } else {
animationTime = delay; animationTime = delay;
return null;
} }
}, },
() => { () => {
// If idle timeout is done, make sure the timed login indicator is shown // If idle timeout is done, make sure the timed login indicator is shown
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD && if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
this._authPrompt.visible) this._authPrompt.actor.visible)
this._authPrompt.cancel(); this._authPrompt.cancel();
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) { if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) {
this._userList.scrollToItem(loginItem); this._userList.scrollToItem(loginItem);
loginItem.grab_key_focus(); loginItem.actor.grab_key_focus();
} }
}, },
@@ -1090,8 +1088,9 @@ var LoginDialog = GObject.registerClass({
// Restart timed login on user interaction // Restart timed login on user interaction
global.stage.connect('captured-event', (actor, event) => { global.stage.connect('captured-event', (actor, event) => {
if (event.type() == Clutter.EventType.KEY_PRESS || if (event.type() == Clutter.EventType.KEY_PRESS ||
event.type() == Clutter.EventType.BUTTON_PRESS) event.type() == Clutter.EventType.BUTTON_PRESS) {
this._startTimedLogin(userName, seconds); this._startTimedLogin(userName, seconds);
}
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}); });
@@ -1125,7 +1124,7 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton.close(); this._sessionMenuButton.close();
this._setUserListExpanded(true); this._setUserListExpanded(true);
this._notListedButton.show(); this._notListedButton.show();
this._userList.grab_key_focus(); this._userList.actor.grab_key_focus();
} }
_beginVerificationForItem(item) { _beginVerificationForItem(item) {
@@ -1134,7 +1133,8 @@ var LoginDialog = GObject.registerClass({
let userName = item.user.get_user_name(); let userName = item.user.get_user_name();
let hold = new Batch.Hold(); let hold = new Batch.Hold();
this._authPrompt.begin({ userName, hold }); this._authPrompt.begin({ userName: userName,
hold: hold });
return hold; return hold;
} }
@@ -1197,8 +1197,9 @@ var LoginDialog = GObject.registerClass({
let users = this._userManager.list_users(); let users = this._userManager.list_users();
for (let i = 0; i < users.length; i++) for (let i = 0; i < users.length; i++) {
this._userList.addUser(users[i]); this._userList.addUser(users[i]);
}
this._updateDisableUserList(); this._updateDisableUserList();
@@ -1231,17 +1232,16 @@ var LoginDialog = GObject.registerClass({
_("Login Window"), _("Login Window"),
'dialog-password-symbolic', 'dialog-password-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE }); { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
this._userList.grab_key_focus(); this._userList.actor.grab_key_focus();
this.show(); this.show();
this.opacity = 0; this.opacity = 0;
Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN }); Main.pushModal(this, { actionMode: Shell.ActionMode.LOGIN_SCREEN });
this.ease({ Tweener.addTween(this,
opacity: 255, { opacity: 255,
duration: 1000, time: 1,
mode: Clutter.AnimationMode.EASE_IN_QUAD, transition: 'easeInQuad' });
});
return true; return true;
} }
@@ -1255,7 +1255,7 @@ var LoginDialog = GObject.registerClass({
this._authPrompt.cancel(); this._authPrompt.cancel();
} }
addCharacter(_unichar) { addCharacter(unichar) {
// Don't allow type ahead at the login screen // Don't allow type ahead at the login screen
} }

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getOVirtCredentialsManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Signals = imports.signals; const Signals = imports.signals;
@@ -23,7 +22,7 @@ function OVirtCredentials() {
g_interface_info: OVirtCredentialsInfo, g_interface_info: OVirtCredentialsInfo,
g_name: 'org.ovirt.vdsm.Credentials', g_name: 'org.ovirt.vdsm.Credentials',
g_object_path: '/org/ovirt/vdsm/Credentials', g_object_path: '/org/ovirt/vdsm/Credentials',
g_flags: Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES }); g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self.init(null); self.init(null);
return self; return self;
} }

View File

@@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -15,13 +16,12 @@ const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface); const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = class { var Manager = class {
constructor() { constructor(parentActor) {
this._aggregateProvider = Provider(Gio.DBus.system, this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd', 'org.freedesktop.realmd',
'/org/freedesktop/realmd', '/org/freedesktop/realmd',
this._reloadRealms.bind(this)); this._reloadRealms.bind(this))
this._realms = {}; this._realms = {};
this._loginFormat = null;
this._signalId = this._aggregateProvider.connect('g-properties-changed', this._signalId = this._aggregateProvider.connect('g-properties-changed',
(proxy, properties) => { (proxy, properties) => {
@@ -37,7 +37,7 @@ var Manager = class {
return; return;
for (let i = 0; i < realmPaths.length; i++) { for (let i = 0; i < realmPaths.length; i++) {
Realm(Gio.DBus.system, let realm = Realm(Gio.DBus.system,
'org.freedesktop.realmd', 'org.freedesktop.realmd',
realmPaths[i], realmPaths[i],
this._onRealmLoaded.bind(this)); this._onRealmLoaded.bind(this));
@@ -87,7 +87,7 @@ var Manager = class {
} }
get loginFormat() { get loginFormat() {
if (this._loginFormat) if (this._loginFormat !== undefined)
return this._loginFormat; return this._loginFormat;
this._updateLoginFormat(); this._updateLoginFormat();
@@ -99,10 +99,10 @@ var Manager = class {
Service(Gio.DBus.system, Service(Gio.DBus.system,
'org.freedesktop.realmd', 'org.freedesktop.realmd',
'/org/freedesktop/realmd', '/org/freedesktop/realmd',
service => service.ReleaseRemote()); service => { service.ReleaseRemote(); });
this._aggregateProvider.disconnect(this._signalId); this._aggregateProvider.disconnect(this._signalId);
this._realms = { }; this._realms = { };
this._updateLoginFormat(); this._updateLoginFormat();
} }
}; };
Signals.addSignalMethods(Manager.prototype); Signals.addSignalMethods(Manager.prototype)

View File

@@ -1,23 +1,27 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
const { Clutter, Gio, GLib } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint; const Fprint = imports.gdm.fingerprint;
const OVirt = imports.gdm.oVirt; const OVirt = imports.gdm.oVirt;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
const SmartcardManager = imports.misc.smartcardManager; const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
var PASSWORD_SERVICE_NAME = 'gdm-password'; var PASSWORD_SERVICE_NAME = 'gdm-password';
var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
var SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; var SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
var OVIRT_SERVICE_NAME = 'gdm-ovirtcred'; var OVIRT_SERVICE_NAME = 'gdm-ovirtcred';
var FADE_ANIMATION_TIME = 160; var FADE_ANIMATION_TIME = 0.16;
var CLONE_FADE_ANIMATION_TIME = 250; var CLONE_FADE_ANIMATION_TIME = 0.25;
var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; var LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication'; var PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
@@ -31,13 +35,13 @@ var LOGO_KEY = 'logo';
var DISABLE_USER_LIST_KEY = 'disable-user-list'; var DISABLE_USER_LIST_KEY = 'disable-user-list';
// Give user 48ms to read each character of a PAM message // Give user 48ms to read each character of a PAM message
var USER_READ_TIME = 48; var USER_READ_TIME = 48
var MessageType = { var MessageType = {
NONE: 0, NONE: 0,
ERROR: 1, ERROR: 1,
INFO: 2, INFO: 2,
HINT: 3, HINT: 3
}; };
function fadeInActor(actor) { function fadeInActor(actor) {
@@ -46,16 +50,16 @@ function fadeInActor(actor) {
let hold = new Batch.Hold(); let hold = new Batch.Hold();
actor.show(); actor.show();
let [, naturalHeight] = actor.get_preferred_height(-1); let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
actor.opacity = 0; actor.opacity = 0;
actor.set_height(0); actor.set_height(0);
actor.ease({ Tweener.addTween(actor,
opacity: 255, { opacity: 255,
height: naturalHeight, height: naturalHeight,
duration: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete() {
this.set_height(-1); this.set_height(-1);
hold.release(); hold.release();
}, },
@@ -72,12 +76,12 @@ function fadeOutActor(actor) {
} }
let hold = new Batch.Hold(); let hold = new Batch.Hold();
actor.ease({ Tweener.addTween(actor,
opacity: 0, { opacity: 0,
height: 0, height: 0,
duration: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete() {
this.hide(); this.hide();
this.set_height(-1); this.set_height(-1);
hold.release(); hold.release();
@@ -102,14 +106,14 @@ function cloneAndFadeOutActor(actor) {
clone.set_position(x, y); clone.set_position(x, y);
let hold = new Batch.Hold(); let hold = new Batch.Hold();
clone.ease({ Tweener.addTween(clone,
opacity: 0, { opacity: 0,
duration: CLONE_FADE_ANIMATION_TIME, time: CLONE_FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete() {
clone.destroy(); clone.destroy();
hold.release(); hold.release();
}, }
}); });
return hold; return hold;
} }
@@ -272,7 +276,7 @@ var ShellUserVerifier = class {
let interval = this._getIntervalForMessage(message); let interval = this._getIntervalForMessage(message);
this.hasPendingMessages = true; this.hasPendingMessages = true;
this._messageQueue.push({ text: message, type: messageType, interval }); this._messageQueue.push({ text: message, type: messageType, interval: interval });
this._queueMessageTimeout(); this._queueMessageTimeout();
} }
@@ -304,7 +308,7 @@ var ShellUserVerifier = class {
}); });
} }
_oVirtUserAuthenticated(_token) { _oVirtUserAuthenticated(token) {
this._preemptingService = OVIRT_SERVICE_NAME; this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated'); this.emit('ovirt-user-authenticated');
} }
@@ -343,7 +347,7 @@ var ShellUserVerifier = class {
try { try {
this._clearUserVerifier(); this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result); this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch (e) { } catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return; return;
if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) && if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
@@ -370,7 +374,7 @@ var ShellUserVerifier = class {
try { try {
this._clearUserVerifier(); this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result); this._userVerifier = client.get_user_verifier_finish(result);
} catch (e) { } catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return; return;
this._reportInitError('Failed to obtain user verifier', e); this._reportInitError('Failed to obtain user verifier', e);
@@ -424,10 +428,13 @@ var ShellUserVerifier = class {
_startService(serviceName) { _startService(serviceName) {
this._hold.acquire(); this._hold.acquire();
if (this._userName) { if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => { this._userVerifier.call_begin_verification_for_user(serviceName,
this._userName,
this._cancellable,
(obj, result) => {
try { try {
obj.call_begin_verification_for_user_finish(result); obj.call_begin_verification_for_user_finish(result);
} catch (e) { } catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return; return;
this._reportInitError('Failed to start verification for user', e); this._reportInitError('Failed to start verification for user', e);
@@ -437,10 +444,12 @@ var ShellUserVerifier = class {
this._hold.release(); this._hold.release();
}); });
} else { } else {
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => { this._userVerifier.call_begin_verification(serviceName,
this._cancellable,
(obj, result) => {
try { try {
obj.call_begin_verification_finish(result); obj.call_begin_verification_finish(result);
} catch (e) { } catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return; return;
this._reportInitError('Failed to start verification', e); this._reportInitError('Failed to start verification', e);
@@ -544,7 +553,6 @@ var ShellUserVerifier = class {
}); });
} }
} else { } else {
// eslint-disable-next-line no-lonely-if
if (!this.hasPendingMessages) { if (!this.hasPendingMessages) {
this._cancelAndReset(); this._cancelAndReset();
} else { } else {
@@ -572,8 +580,9 @@ var ShellUserVerifier = class {
// if the password service fails, then cancel everything. // if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give // But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed // password authentication a chance to succeed
if (this.serviceIsForeground(serviceName)) if (this.serviceIsForeground(serviceName)) {
this._verificationFailed(true); this._verificationFailed(true);
} }
}
}; };
Signals.addSignalMethods(ShellUserVerifier.prototype); Signals.addSignalMethods(ShellUserVerifier.prototype);

View File

@@ -64,7 +64,6 @@
<file>ui/keyboard.js</file> <file>ui/keyboard.js</file>
<file>ui/layout.js</file> <file>ui/layout.js</file>
<file>ui/lightbox.js</file> <file>ui/lightbox.js</file>
<file>ui/locatePointer.js</file>
<file>ui/lookingGlass.js</file> <file>ui/lookingGlass.js</file>
<file>ui/magnifier.js</file> <file>ui/magnifier.js</file>
<file>ui/magnifierDBus.js</file> <file>ui/magnifierDBus.js</file>
@@ -79,14 +78,11 @@
<file>ui/overview.js</file> <file>ui/overview.js</file>
<file>ui/overviewControls.js</file> <file>ui/overviewControls.js</file>
<file>ui/padOsd.js</file> <file>ui/padOsd.js</file>
<file>ui/pageIndicators.js</file>
<file>ui/panel.js</file> <file>ui/panel.js</file>
<file>ui/panelMenu.js</file> <file>ui/panelMenu.js</file>
<file>ui/pointerA11yTimeout.js</file>
<file>ui/pointerWatcher.js</file> <file>ui/pointerWatcher.js</file>
<file>ui/popupMenu.js</file> <file>ui/popupMenu.js</file>
<file>ui/remoteSearch.js</file> <file>ui/remoteSearch.js</file>
<file>ui/ripples.js</file>
<file>ui/runDialog.js</file> <file>ui/runDialog.js</file>
<file>ui/screenShield.js</file> <file>ui/screenShield.js</file>
<file>ui/screencast.js</file> <file>ui/screencast.js</file>
@@ -123,7 +119,6 @@
<file>ui/status/accessibility.js</file> <file>ui/status/accessibility.js</file>
<file>ui/status/brightness.js</file> <file>ui/status/brightness.js</file>
<file>ui/status/dwellClick.js</file>
<file>ui/status/location.js</file> <file>ui/status/location.js</file>
<file>ui/status/keyboard.js</file> <file>ui/status/keyboard.js</file>
<file>ui/status/nightLight.js</file> <file>ui/status/nightLight.js</file>

View File

@@ -1,52 +1,36 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionState, ExtensionType, getCurrentExtension,
getSettings, initTranslations, isOutOfDate, installImporter,
serializeExtension, deserializeExtension */
// Common utils for the extension system and the extension // Common utils for the extension system and the extension
// preferences tool // preferences tool
const { Gio, GLib } = imports.gi; const Signals = imports.signals;
const Gettext = imports.gettext; const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Config = imports.misc.config; const Config = imports.misc.config;
const FileUtils = imports.misc.fileUtils;
var ExtensionType = { var ExtensionType = {
SYSTEM: 1, SYSTEM: 1,
PER_USER: 2, PER_USER: 2
}; };
var ExtensionState = { // Maps uuid -> metadata object
ENABLED: 1, var extensions = {};
DISABLED: 2,
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
UNINSTALLED: 99,
};
const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange'];
/** /**
* getCurrentExtension: * getCurrentExtension:
* *
* @returns {?object} - The current extension, or null if not called from * Returns the current extension, or null if not called from an extension.
* an extension.
*/ */
function getCurrentExtension() { function getCurrentExtension() {
let stack = new Error().stack.split('\n'); let stack = (new Error()).stack.split('\n');
let extensionStackLine; let extensionStackLine;
// Search for an occurrence of an extension stack frame // Search for an occurrence of an extension stack frame
// Start at 1 because 0 is the stack frame of this function // Start at 1 because 0 is the stack frame of this function
for (let i = 1; i < stack.length; i++) { for (let i = 1; i < stack.length; i++) {
if (stack[i].includes('/gnome-shell/extensions/')) { if (stack[i].indexOf('/gnome-shell/extensions/') > -1) {
extensionStackLine = stack[i]; extensionStackLine = stack[i];
break; break;
} }
@@ -64,17 +48,13 @@ function getCurrentExtension() {
if (!match) if (!match)
return null; return null;
// local import, as the module is used from outside the gnome-shell process
// as well (not this function though)
let extensionManager = imports.ui.main.extensionManager;
let path = match[1]; let path = match[1];
let file = Gio.File.new_for_path(path); let file = Gio.File.new_for_path(path);
// Walk up the directory tree, looking for an extension with // Walk up the directory tree, looking for an extension with
// the same UUID as a directory name. // the same UUID as a directory name.
while (file != null) { while (file != null) {
let extension = extensionManager.lookup(file.get_basename()); let extension = extensions[file.get_basename()];
if (extension !== undefined) if (extension !== undefined)
return extension; return extension;
file = file.get_parent(); file = file.get_parent();
@@ -83,73 +63,10 @@ function getCurrentExtension() {
return null; return null;
} }
/**
* initTranslations:
* @param {string=} domain - the gettext domain to use
*
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
function initTranslations(domain) {
let extension = getCurrentExtension();
if (!extension)
throw new Error('initTranslations() can only be called from extensions');
domain = domain || extension.metadata['gettext-domain'];
// Expect USER extensions to have a locale/ subfolder, otherwise assume a
// SYSTEM extension that has been installed in the same prefix as the shell
let localeDir = extension.dir.get_child('locale');
if (localeDir.query_exists(null))
Gettext.bindtextdomain(domain, localeDir.get_path());
else
Gettext.bindtextdomain(domain, Config.LOCALEDIR);
}
/**
* getSettings:
* @param {string=} schema - the GSettings schema id
* @returns {Gio.Settings} - a new settings object for @schema
*
* Builds and returns a GSettings schema for @schema, using schema files
* in extensionsdir/schemas. If @schema is omitted, it is taken from
* metadata['settings-schema'].
*/
function getSettings(schema) {
let extension = getCurrentExtension();
if (!extension)
throw new Error('getSettings() can only be called from extensions');
schema = schema || extension.metadata['settings-schema'];
const GioSSS = Gio.SettingsSchemaSource;
// Expect USER extensions to have a schemas/ subfolder, otherwise assume a
// SYSTEM extension that has been installed in the same prefix as the shell
let schemaDir = extension.dir.get_child('schemas');
let schemaSource;
if (schemaDir.query_exists(null)) {
schemaSource = GioSSS.new_from_directory(schemaDir.get_path(),
GioSSS.get_default(),
false);
} else {
schemaSource = GioSSS.get_default();
}
let schemaObj = schemaSource.lookup(schema, true);
if (!schemaObj)
throw new Error(`Schema ${schema} could not be found for extension ${extension.metadata.uuid}. Please check your installation`);
return new Gio.Settings({ settings_schema: schemaObj });
}
/** /**
* versionCheck: * versionCheck:
* @param {string[]} required - an array of versions we're compatible with * @required: an array of versions we're compatible with
* @param {string} current - the version we have * @current: the version we have
* @returns {bool} - true if @current is compatible with @required
* *
* Check if a component is compatible for an extension. * Check if a component is compatible for an extension.
* @required is an array, and at least one version must match. * @required is an array, and at least one version must match.
@@ -169,8 +86,8 @@ function versionCheck(required, current) {
let requiredArray = required[i].split('.'); let requiredArray = required[i].split('.');
if (requiredArray[0] == major && if (requiredArray[0] == major &&
requiredArray[1] == minor && requiredArray[1] == minor &&
((requiredArray[2] === undefined && parseInt(minor) % 2 == 0) || (requiredArray[2] == point ||
requiredArray[2] == point)) (requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
return true; return true;
} }
return false; return false;
@@ -183,50 +100,54 @@ function isOutOfDate(extension) {
return false; return false;
} }
function serializeExtension(extension) { function createExtensionObject(uuid, dir, type) {
let obj = {}; let info;
Lang.copyProperties(extension.metadata, obj);
SERIALIZED_PROPERTIES.forEach(prop => { let metadataFile = dir.get_child('metadata.json');
obj[prop] = extension[prop]; if (!metadataFile.query_exists(null)) {
}); throw new Error('Missing metadata.json');
let res = {};
for (let key in obj) {
let val = obj[key];
let type;
switch (typeof val) {
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
case 'boolean':
type = 'b';
break;
default:
continue;
}
res[key] = GLib.Variant.new(type, val);
} }
return res; let metadataContents, success, tag;
} try {
[success, metadataContents, tag] = metadataFile.load_contents(null);
function deserializeExtension(variant) { if (metadataContents instanceof Uint8Array)
let res = { metadata: {} }; metadataContents = imports.byteArray.toString(metadataContents);
for (let prop in variant) { } catch (e) {
let val = variant[prop].unpack(); throw new Error('Failed to load metadata.json: ' + e);
if (SERIALIZED_PROPERTIES.includes(prop))
res[prop] = val;
else
res.metadata[prop] = val;
} }
// add the 2 additional properties to create a valid extension object, as createExtensionObject() let meta;
res.uuid = res.metadata.uuid; try {
res.dir = Gio.File.new_for_path(res.path); meta = JSON.parse(metadataContents);
return res; } catch (e) {
throw new Error('Failed to parse metadata.json: ' + e);
}
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i];
if (!meta[prop]) {
throw new Error('missing "' + prop + '" property in metadata.json');
}
}
if (uuid != meta.uuid) {
throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
}
let extension = {};
extension.metadata = meta;
extension.uuid = meta.uuid;
extension.type = type;
extension.dir = dir;
extension.path = dir.get_path();
extension.error = '';
extension.hasPrefs = dir.get_child('prefs.js').query_exists(null);
extensions[uuid] = extension;
return extension;
} }
function installImporter(extension) { function installImporter(extension) {
@@ -237,3 +158,36 @@ function installImporter(extension) {
extension.imports = imports[extension.uuid]; extension.imports = imports[extension.uuid];
imports.searchPath = oldSearchPath; imports.searchPath = oldSearchPath;
} }
var ExtensionFinder = class {
_loadExtension(extensionDir, info, perUserDir) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
let uuid = info.get_name();
let existing = extensions[uuid];
if (existing) {
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path()));
return;
}
let extension;
let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER
: ExtensionType.SYSTEM;
try {
extension = createExtensionObject(uuid, extensionDir, type);
} catch(e) {
logError(e, 'Could not load extension %s'.format(uuid));
return;
}
this.emit('extension-found', extension);
}
scanExtensions() {
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
this._loadExtension(dir, info, perUserDir);
});
}
};
Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@@ -1,9 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported collectFromDatadirs, recursivelyDeleteDir,
recursivelyMoveDir, loadInterfaceXML */
const { Gio, GLib } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Config = imports.misc.config; const Config = imports.misc.config;
const Params = imports.misc.params;
function collectFromDatadirs(subdir, includeUserDir, processFile) { function collectFromDatadirs(subdir, includeUserDir, processFile) {
let dataDirs = GLib.get_system_data_dirs(); let dataDirs = GLib.get_system_data_dirs();
@@ -29,22 +29,27 @@ function collectFromDatadirs(subdir, includeUserDir, processFile) {
} }
} }
function deleteGFile(file) {
// Work around 'delete' being a keyword in JS.
return file['delete'](null);
}
function recursivelyDeleteDir(dir, deleteParent) { function recursivelyDeleteDir(dir, deleteParent) {
let children = dir.enumerate_children('standard::name,standard::type', let children = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null); Gio.FileQueryInfoFlags.NONE, null);
let info; let info, child;
while ((info = children.next_file(null)) != null) { while ((info = children.next_file(null)) != null) {
let type = info.get_file_type(); let type = info.get_file_type();
let child = dir.get_child(info.get_name()); let child = dir.get_child(info.get_name());
if (type == Gio.FileType.REGULAR) if (type == Gio.FileType.REGULAR)
child.delete(null); deleteGFile(child);
else if (type == Gio.FileType.DIRECTORY) else if (type == Gio.FileType.DIRECTORY)
recursivelyDeleteDir(child, true); recursivelyDeleteDir(child, true);
} }
if (deleteParent) if (deleteParent)
dir.delete(null); deleteGFile(dir);
} }
function recursivelyMoveDir(srcDir, destDir) { function recursivelyMoveDir(srcDir, destDir) {
@@ -54,7 +59,7 @@ function recursivelyMoveDir(srcDir, destDir) {
if (!destDir.query_exists(null)) if (!destDir.query_exists(null))
destDir.make_directory_with_parents(null); destDir.make_directory_with_parents(null);
let info; let info, child;
while ((info = children.next_file(null)) != null) { while ((info = children.next_file(null)) != null) {
let type = info.get_file_type(); let type = info.get_file_type();
let srcChild = srcDir.get_child(info.get_name()); let srcChild = srcDir.get_child(info.get_name());
@@ -70,24 +75,24 @@ let _ifaceResource = null;
function loadInterfaceXML(iface) { function loadInterfaceXML(iface) {
if (!_ifaceResource) { if (!_ifaceResource) {
// don't use global.datadir so the method is usable from tests/tools // don't use global.datadir so the method is usable from tests/tools
let dir = GLib.getenv('GNOME_SHELL_DATADIR') || Config.PKGDATADIR; let dir = GLib.getenv ('GNOME_SHELL_DATADIR') || Config.PKGDATADIR;
let path = `${dir}/gnome-shell-dbus-interfaces.gresource`; let path = dir + '/gnome-shell-dbus-interfaces.gresource';
_ifaceResource = Gio.Resource.load(path); _ifaceResource = Gio.Resource.load(path);
_ifaceResource._register(); _ifaceResource._register();
} }
let xml = null; let xml = null;
let uri = `resource:///org/gnome/shell/dbus-interfaces/${iface}.xml`; let uri = 'resource:///org/gnome/shell/dbus-interfaces/' + iface + '.xml';
let f = Gio.File.new_for_uri(uri); let f = Gio.File.new_for_uri(uri);
try { try {
let [ok_, bytes] = f.load_contents(null); let [ok, bytes] = f.load_contents(null);
if (bytes instanceof Uint8Array) if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes); xml = imports.byteArray.toString(bytes)
else else
xml = bytes.toString(); xml = bytes.toString();
} catch (e) { } catch (e) {
log(`Failed to load D-Bus interface ${iface}`); log('Failed to load D-Bus interface ' + iface);
} }
return xml; return xml;

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PresenceStatus, Presence, Inhibitor, SessionManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -11,7 +11,7 @@ var PresenceStatus = {
AVAILABLE: 0, AVAILABLE: 0,
INVISIBLE: 1, INVISIBLE: 1,
BUSY: 2, BUSY: 2,
IDLE: 3, IDLE: 3
}; };
var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface); var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);

View File

@@ -18,7 +18,7 @@ var HistoryManager = class {
this._historyIndex = 0; this._historyIndex = 0;
if (this._key) { if (this._key) {
this._history = global.settings.get_strv(this._key); this._history = global.settings.get_strv(this._key);
global.settings.connect(`changed::${this._key}`, global.settings.connect('changed::' + this._key,
this._historyChanged.bind(this)); this._historyChanged.bind(this));
} else { } else {
@@ -66,7 +66,7 @@ var HistoryManager = class {
this._indexChanged(); this._indexChanged();
} }
return this._historyIndex ? this._history[this._historyIndex - 1] : null; return this._historyIndex ? this._history[this._historyIndex -1] : null;
} }
addItem(input) { addItem(input) {
@@ -82,11 +82,11 @@ var HistoryManager = class {
_onEntryKeyPress(entry, event) { _onEntryKeyPress(entry, event) {
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Up) if (symbol == Clutter.KEY_Up) {
return this._setPrevItem(entry.get_text()); return this._setPrevItem(entry.get_text());
else if (symbol == Clutter.KEY_Down) } else if (symbol == Clutter.KEY_Down) {
return this._setNextItem(entry.get_text()); return this._setNextItem(entry.get_text());
}
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }

View File

@@ -1,9 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */
const { Gio, GLib, IBus } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const IBus = imports.gi.IBus;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup; const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
// Ensure runtime version matches // Ensure runtime version matches
@@ -18,8 +20,8 @@ function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
IBus.MICRO_VERSION >= requiredMicro)) IBus.MICRO_VERSION >= requiredMicro))
return; return;
throw "Found IBus version %d.%d.%d but required is %d.%d.%d" throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
.format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION, format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro); requiredMajor, requiredMinor, requiredMicro);
} }
@@ -42,7 +44,7 @@ var IBusManager = class {
this._candidatePopup = new IBusCandidatePopup.CandidatePopup(); this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._panelService = null; this._panelService = null;
this._engines = new Map(); this._engines = {};
this._ready = false; this._ready = false;
this._registerPropertiesId = 0; this._registerPropertiesId = 0;
this._currentEngineName = null; this._currentEngineName = null;
@@ -58,79 +60,54 @@ var IBusManager = class {
this._spawn(); this._spawn();
} }
_spawn(extraArgs = []) { _spawn() {
try { try {
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs]; Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.Subprocess.new(cmdLine, Gio.SubprocessFlags.NONE); Gio.SubprocessFlags.NONE);
} catch (e) { } catch(e) {
log(`Failed to launch ibus-daemon: ${e.message}`); log('Failed to launch ibus-daemon: ' + e.message);
} }
} }
restartDaemon(extraArgs = []) {
this._spawn(['-r', ...extraArgs]);
}
_clear() { _clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
if (this._preloadEnginesId) {
GLib.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
if (this._panelService) if (this._panelService)
this._panelService.destroy(); this._panelService.destroy();
this._panelService = null; this._panelService = null;
this._candidatePopup.setPanelService(null); this._candidatePopup.setPanelService(null);
this._engines.clear(); this._engines = {};
this._ready = false; this._ready = false;
this._registerPropertiesId = 0; this._registerPropertiesId = 0;
this._currentEngineName = null; this._currentEngineName = null;
this.emit('ready', false); this.emit('ready', false);
this._spawn();
} }
_onConnected() { _onConnected() {
this._cancellable = new Gio.Cancellable(); this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL, this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable, IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
this._initPanelService.bind(this)); this._initPanelService.bind(this));
} }
_initEngines(ibus, result) { _initEngines(ibus, result) {
try {
let enginesList = this._ibus.list_engines_async_finish(result); let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) { for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name(); let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]); this._engines[name] = enginesList[i];
} }
this._updateReadiness(); this._updateReadiness();
} catch (e) { } else {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
this._clear(); this._clear();
} }
} }
_initPanelService(ibus, result) { _initPanelService(ibus, result) {
let success = false; let success = this._ibus.request_name_async_finish(result);
try {
success = !!this._ibus.request_name_async_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
}
if (success) { if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(), this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL }); object_path: IBus.PATH_PANEL });
@@ -142,9 +119,9 @@ var IBusManager = class {
}); });
this._panelService.connect('focus-in', (panel, path) => { this._panelService.connect('focus-in', (panel, path) => {
if (!GLib.str_has_suffix(path, '/InputContext_1')) if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit('focus-in'); this.emit ('focus-in');
}); });
this._panelService.connect('focus-out', () => this.emit('focus-out')); this._panelService.connect('focus-out', () => { this.emit('focus-out'); });
try { try {
// IBus versions older than 1.5.10 have a bug which // IBus versions older than 1.5.10 have a bug which
@@ -157,13 +134,13 @@ var IBusManager = class {
} catch (e) { } catch (e) {
} }
// If an engine is already active we need to get its properties // If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => { this._ibus.get_global_engine_async(-1, null, (i, result) => {
let engine; let engine;
try { try {
engine = this._ibus.get_global_engine_async_finish(res); engine = this._ibus.get_global_engine_async_finish(result);
if (!engine) if (!engine)
return; return;
} catch (e) { } catch(e) {
return; return;
} }
this._engineChanged(this._ibus, engine.get_name()); this._engineChanged(this._ibus, engine.get_name());
@@ -175,7 +152,8 @@ var IBusManager = class {
} }
_updateReadiness() { _updateReadiness() {
this._ready = this._engines.size > 0 && this._panelService != null; this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this.emit('ready', this._ready); this.emit('ready', this._ready);
} }
@@ -213,10 +191,10 @@ var IBusManager = class {
} }
getEngineDesc(id) { getEngineDesc(id) {
if (!this._ready || !this._engines.has(id)) if (!this._ready || !this._engines.hasOwnProperty(id))
return null; return null;
return this._engines.get(id); return this._engines[id];
} }
setEngine(id, callback) { setEngine(id, callback) {
@@ -229,18 +207,8 @@ var IBusManager = class {
return; return;
} }
this._ibus.set_global_engine_async(id, this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME, null, callback || null);
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
} }
preloadEngines(ids) { preloadEngines(ids) {
@@ -248,19 +216,17 @@ var IBusManager = class {
return; return;
if (this._preloadEnginesId != 0) { if (this._preloadEnginesId != 0) {
GLib.source_remove(this._preloadEnginesId); Mainloop.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0; this._preloadEnginesId = 0;
} }
this._preloadEnginesId = this._preloadEnginesId =
GLib.timeout_add_seconds( Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
GLib.PRIORITY_DEFAULT,
this._PRELOAD_ENGINES_DELAY_TIME,
() => { () => {
this._ibus.preload_engines_async( this._ibus.preload_engines_async(
ids, ids,
-1, -1,
this._cancellable, null,
null); null);
this._preloadEnginesId = 0; this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;

View File

@@ -1,10 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputMethod */ const Clutter = imports.gi.Clutter;
const { Clutter, GLib, Gio, GObject, IBus } = imports.gi; const GObject = imports.gi.GObject;
const IBus = imports.gi.IBus;
const Keyboard = imports.ui.status.keyboard; const Keyboard = imports.ui.status.keyboard;
const Signals = imports.signals;
var HIDE_PANEL_TIME = 50;
var InputMethod = GObject.registerClass( var InputMethod = GObject.registerClass(
class InputMethod extends Clutter.InputMethod { class InputMethod extends Clutter.InputMethod {
@@ -16,7 +15,6 @@ class InputMethod extends Clutter.InputMethod {
this._preeditStr = ''; this._preeditStr = '';
this._preeditPos = 0; this._preeditPos = 0;
this._preeditVisible = false; this._preeditVisible = false;
this._hidePanelId = 0;
this._ibus = IBus.Bus.new_async(); this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', this._onConnected.bind(this)); this._ibus.connect('connected', this._onConnected.bind(this));
this._ibus.connect('disconnected', this._clear.bind(this)); this._ibus.connect('disconnected', this._clear.bind(this));
@@ -36,7 +34,15 @@ class InputMethod extends Clutter.InputMethod {
} }
_updateCapabilities() { _updateCapabilities() {
let caps = IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT; let caps = 0;
if (this.can_show_preedit)
caps |= IBus.Capabilite.PREEDIT_TEXT;
if (this._currentFocus)
caps |= IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT;
else
caps |= IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.AUXILIARY_TEXT | IBus.Capabilite.LOOKUP_TABLE | IBus.Capabilite.PROPERTY;
if (this._context) if (this._context)
this._context.set_capabilities(caps); this._context.set_capabilities(caps);
@@ -47,43 +53,27 @@ class InputMethod extends Clutter.InputMethod {
} }
_onConnected() { _onConnected() {
this._cancellable = new Gio.Cancellable(); this._ibus.create_input_context_async ('gnome-shell', -1, null,
this._ibus.create_input_context_async('gnome-shell', -1, this._setContext.bind(this));
this._cancellable, this._setContext.bind(this));
} }
_setContext(bus, res) { _setContext(bus, res) {
try {
this._context = this._ibus.create_input_context_async_finish(res); this._context = this._ibus.create_input_context_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
this._clear();
}
return;
}
this._context.connect('commit-text', this._onCommitText.bind(this)); this._context.connect('commit-text', this._onCommitText.bind(this));
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this)); this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this)); this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
this._context.connect('show-preedit-text', this._onShowPreeditText.bind(this)); this._context.connect('show-preedit-text', this._onShowPreeditText.bind(this));
this._context.connect('hide-preedit-text', this._onHidePreeditText.bind(this)); this._context.connect('hide-preedit-text', this._onHidePreeditText.bind(this));
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this)); this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
this._context.connect('destroy', this._clear.bind(this));
this._updateCapabilities(); this._updateCapabilities();
} }
_clear() { _clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
this._context = null; this._context = null;
this._hints = 0; this._hints = 0;
this._purpose = 0; this._purpose = 0;
this._preeditStr = ''; this._preeditStr = ''
this._preeditPos = 0; this._preeditPos = 0;
this._preeditVisible = false; this._preeditVisible = false;
} }
@@ -93,15 +83,15 @@ class InputMethod extends Clutter.InputMethod {
this.emit('request-surrounding'); this.emit('request-surrounding');
} }
_onCommitText(_context, text) { _onCommitText(context, text) {
this.commit(text.get_text()); this.commit(text.get_text());
} }
_onDeleteSurroundingText() { _onDeleteSurroundingText(context) {
this.delete_surrounding(); this.delete_surrounding();
} }
_onUpdatePreeditText(_context, text, pos, visible) { _onUpdatePreeditText(context, text, pos, visible) {
if (text == null) if (text == null)
return; return;
@@ -117,19 +107,19 @@ class InputMethod extends Clutter.InputMethod {
this._preeditVisible = visible; this._preeditVisible = visible;
} }
_onShowPreeditText() { _onShowPreeditText(context) {
this._preeditVisible = true; this._preeditVisible = true;
this.set_preedit_text(this._preeditStr, this._preeditPos); this.set_preedit_text(this._preeditStr, this._preeditPos);
} }
_onHidePreeditText() { _onHidePreeditText(context) {
this.set_preedit_text(null, this._preeditPos); this.set_preedit_text(null, this._preeditPos);
this._preeditVisible = false; this._preeditVisible = false;
} }
_onForwardKeyEvent(_context, keyval, keycode, state) { _onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0; let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
state &= ~IBus.ModifierType.RELEASE_MASK; state &= ~(IBus.ModifierType.RELEASE_MASK);
let curEvent = Clutter.get_current_event(); let curEvent = Clutter.get_current_event();
let time; let time;
@@ -145,31 +135,23 @@ class InputMethod extends Clutter.InputMethod {
this._currentFocus = focus; this._currentFocus = focus;
if (this._context) { if (this._context) {
this._context.focus_in(); this._context.focus_in();
this._updateCapabilities();
this._emitRequestSurrounding(); this._emitRequestSurrounding();
} }
if (this._hidePanelId) {
GLib.source_remove(this._hidePanelId);
this._hidePanelId = 0;
}
} }
vfunc_focus_out() { vfunc_focus_out() {
this._currentFocus = null; this._currentFocus = null;
if (this._context) if (this._context) {
this._context.focus_out(); this._context.focus_out();
this._updateCapabilities();
}
if (this._preeditStr) { if (this._preeditStr) {
// Unset any preedit text // Unset any preedit text
this.set_preedit_text(null, 0); this.set_preedit_text(null, 0);
this._preeditStr = null; 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() { vfunc_reset() {
@@ -260,20 +242,15 @@ class InputMethod extends Clutter.InputMethod {
if (event.type() == Clutter.EventType.KEY_RELEASE) if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK; state |= IBus.ModifierType.RELEASE_MASK;
this._context.process_key_event_async( this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, this._cancellable, state, -1, null,
(context, res) => { (context, res) => {
if (context != this._context)
return;
try { try {
let retval = context.process_key_event_async_finish(res); let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval); this.notify_key_event(event, retval);
} catch (e) { } catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) log('Error processing key on IM: ' + e.message);
log(`Error processing key on IM: ${e.message}`);
} }
}); });
return true; return true;

View File

@@ -1,5 +1,7 @@
/* exported IntrospectService */ const Gio = imports.gi.Gio;
const { Gio, GLib, Meta, Shell } = imports.gi; const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const INTROSPECT_SCHEMA = 'org.gnome.shell'; const INTROSPECT_SCHEMA = 'org.gnome.shell';
const INTROSPECT_KEY = 'introspect'; const INTROSPECT_KEY = 'introspect';
@@ -40,18 +42,11 @@ var IntrospectService = class {
}); });
this._syncRunningApplications(); this._syncRunningApplications();
this._whitelistMap = new Map();
APP_WHITELIST.forEach(appName => {
Gio.DBus.watch_name(Gio.BusType.SESSION,
appName,
Gio.BusNameWatcherFlags.NONE,
(conn, name, owner) => this._whitelistMap.set(name, owner),
(conn, name) => this._whitelistMap.delete(name));
});
} }
_isStandaloneApp(app) { _isStandaloneApp(app) {
let windows = app.get_windows();
return app.get_windows().some(w => w.transient_for == null); return app.get_windows().some(w => w.transient_for == null);
} }
@@ -60,12 +55,7 @@ var IntrospectService = class {
} }
_isSenderWhitelisted(sender) { _isSenderWhitelisted(sender) {
return [...this._whitelistMap.values()].includes(sender); return APP_WHITELIST.includes(sender);
}
_getSandboxedAppId(app) {
let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
return ids.find(id => id != null);
} }
_syncRunningApplications() { _syncRunningApplications() {
@@ -79,7 +69,7 @@ var IntrospectService = class {
for (let app of apps) { for (let app of apps) {
let appInfo = {}; let appInfo = {};
let isAppActive = focusedApp == app; let isAppActive = (focusedApp == app);
if (!this._isStandaloneApp(app)) if (!this._isStandaloneApp(app))
continue; continue;
@@ -89,10 +79,6 @@ var IntrospectService = class {
newActiveApplication = app.get_id(); newActiveApplication = app.get_id();
} }
let sandboxedAppId = this._getSandboxedAppId(app);
if (sandboxedAppId)
appInfo['sandboxed-app-id'] = new GLib.Variant('s', sandboxedAppId);
newRunningApplications[app.get_id()] = appInfo; newRunningApplications[app.get_id()] = appInfo;
} }
@@ -113,10 +99,10 @@ var IntrospectService = class {
return false; return false;
let type = window.get_window_type(); let type = window.get_window_type();
return type == Meta.WindowType.NORMAL || return (type == Meta.WindowType.NORMAL ||
type == Meta.WindowType.DIALOG || type == Meta.WindowType.DIALOG ||
type == Meta.WindowType.MODAL_DIALOG || type == Meta.WindowType.MODAL_DIALOG ||
type == Meta.WindowType.UTILITY; type == Meta.WindowType.UTILITY);
} }
GetRunningApplicationsAsync(params, invocation) { GetRunningApplicationsAsync(params, invocation) {
@@ -136,8 +122,7 @@ var IntrospectService = class {
let apps = this._appSystem.get_running(); let apps = this._appSystem.get_running();
let windowsList = {}; let windowsList = {};
if (!this._isIntrospectEnabled() && if (!this._isIntrospectEnabled()) {
!this._isSenderWhitelisted(invocation.get_sender())) {
invocation.return_error_literal(Gio.DBusError, invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED, Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed'); 'App introspection not allowed');
@@ -155,15 +140,14 @@ var IntrospectService = class {
let frameRect = window.get_frame_rect(); let frameRect = window.get_frame_rect();
let title = window.get_title(); let title = window.get_title();
let wmClass = window.get_wm_class(); let wmClass = window.get_wm_class();
let sandboxedAppId = window.get_sandboxed_app_id();
windowsList[windowId] = { windowsList[windowId] = {
'app-id': GLib.Variant.new('s', app.get_id()), 'app-id': GLib.Variant.new('s', app.get_id()),
'client-type': GLib.Variant.new('u', window.get_client_type()), 'client-type': GLib.Variant.new('u', window.get_client_type()),
'is-hidden': GLib.Variant.new('b', window.is_hidden()), 'is-hidden': GLib.Variant.new('b', window.is_hidden()),
'has-focus': GLib.Variant.new('b', window == focusWindow), 'has-focus': GLib.Variant.new('b', (window == focusWindow)),
'width': GLib.Variant.new('u', frameRect.width), 'width': GLib.Variant.new('u', frameRect.width),
'height': GLib.Variant.new('u', frameRect.height), 'height': GLib.Variant.new('u', frameRect.height)
}; };
// These properties may not be available for all windows: // These properties may not be available for all windows:
@@ -172,11 +156,6 @@ var IntrospectService = class {
if (wmClass != null) if (wmClass != null)
windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass); windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
if (sandboxedAppId != null) {
windowsList[windowId]['sandboxed-app-id'] =
GLib.Variant.new('s', sandboxedAppId);
}
} }
} }
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList])); invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));

View File

@@ -1,5 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
// Returns a list of potential completions for text. Completions either // Returns a list of potential completions for text. Completions either
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo) // follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
@@ -9,10 +8,11 @@
// This function is likely the one you want to call from external modules // This function is likely the one you want to call from external modules
function getCompletions(text, commandHeader, globalCompletionList) { function getCompletions(text, commandHeader, globalCompletionList) {
let methods = []; let methods = [];
let expr_, base; let expr, base;
let attrHead = ''; let attrHead = '';
if (globalCompletionList == null) if (globalCompletionList == null) {
globalCompletionList = []; globalCompletionList = [];
}
let offset = getExpressionOffset(text, text.length - 1); let offset = getExpressionOffset(text, text.length - 1);
if (offset >= 0) { if (offset >= 0) {
@@ -21,7 +21,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// Look for expressions like "Main.panel.foo" and match Main.panel and foo // Look for expressions like "Main.panel.foo" and match Main.panel and foo
let matches = text.match(/(.*)\.(.*)/); let matches = text.match(/(.*)\.(.*)/);
if (matches) { if (matches) {
[expr_, base, attrHead] = matches; [expr, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter( methods = getPropertyNamesFromExpression(base, commandHeader).filter(
attr => attr.slice(0, attrHead.length) == attrHead attr => attr.slice(0, attrHead.length) == attrHead
@@ -32,7 +32,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// not proceeded by a dot and match them against global constants // not proceeded by a dot and match them against global constants
matches = text.match(/^(\w*)$/); matches = text.match(/^(\w*)$/);
if (text == '' || matches) { if (text == '' || matches) {
[expr_, attrHead] = matches; [expr, attrHead] = matches;
methods = globalCompletionList.filter( methods = globalCompletionList.filter(
attr => attr.slice(0, attrHead.length) == attrHead attr => attr.slice(0, attrHead.length) == attrHead
); );
@@ -51,25 +51,27 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// if we encounter anything that isn't a letter, '.', ')', or ']', // if we encounter anything that isn't a letter, '.', ')', or ']',
// we should stop parsing. // we should stop parsing.
function isStopChar(c) { function isStopChar(c) {
return !c.match(/[\w.)\]]/); return !c.match(/[\w\.\)\]]/);
} }
// Given the ending position of a quoted string, find where it starts // Given the ending position of a quoted string, find where it starts
function findMatchingQuote(expr, offset) { function findMatchingQuote(expr, offset) {
let quoteChar = expr.charAt(offset); let quoteChar = expr.charAt(offset);
for (let i = offset - 1; i >= 0; --i) { for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == quoteChar && expr.charAt(i - 1) != '\\') if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
return i; return i;
} }
}
return -1; return -1;
} }
// Given the ending position of a regex, find where it starts // Given the ending position of a regex, find where it starts
function findMatchingSlash(expr, offset) { function findMatchingSlash(expr, offset) {
for (let i = offset - 1; i >= 0; --i) { for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\') if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
return i; return i;
} }
}
return -1; return -1;
} }
@@ -79,30 +81,31 @@ function findMatchingSlash(expr, offset) {
// findMatchingBrace("[(])", 3) returns 1. // findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) { function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset); let closeBrace = expr.charAt(offset);
let openBrace = { ')': '(', ']': '[' }[closeBrace]; let openBrace = ({')': '(', ']': '['})[closeBrace];
return findTheBrace(expr, offset - 1, openBrace, closeBrace); function findTheBrace(expr, offset) {
} if (offset < 0) {
function findTheBrace(expr, offset, ...braces) {
let [openBrace, closeBrace] = braces;
if (offset < 0)
return -1; return -1;
}
if (expr.charAt(offset) == openBrace) if (expr.charAt(offset) == openBrace) {
return offset; return offset;
}
if (expr.charAt(offset).match(/['"]/)) {
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
}
if (expr.charAt(offset) == '/') {
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
}
if (expr.charAt(offset) == closeBrace) {
return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
}
if (expr.charAt(offset).match(/['"]/)) return findTheBrace(expr, offset - 1);
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1, ...braces);
if (expr.charAt(offset) == '/') }
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1, ...braces);
if (expr.charAt(offset) == closeBrace) return findTheBrace(expr, offset - 1);
return findTheBrace(expr, findTheBrace(expr, offset - 1, ...braces) - 1, ...braces);
return findTheBrace(expr, offset - 1, ...braces);
} }
// Walk expr backwards from offset looking for the beginning of an // Walk expr backwards from offset looking for the beginning of an
@@ -114,11 +117,13 @@ function getExpressionOffset(expr, offset) {
while (offset >= 0) { while (offset >= 0) {
let currChar = expr.charAt(offset); let currChar = expr.charAt(offset);
if (isStopChar(currChar)) if (isStopChar(currChar)){
return offset + 1; return offset + 1;
}
if (currChar.match(/[)\]]/)) if (currChar.match(/[\)\]]/)) {
offset = findMatchingBrace(expr, offset); offset = findMatchingBrace(expr, offset);
}
--offset; --offset;
} }
@@ -135,10 +140,10 @@ function isValidPropertyName(w) {
// To get all properties (enumerable and not), we need to walk // To get all properties (enumerable and not), we need to walk
// the prototype chain ourselves // the prototype chain ourselves
function getAllProps(obj) { function getAllProps(obj) {
if (obj === null || obj === undefined) if (obj === null || obj === undefined) {
return []; return [];
}
return Object.getOwnPropertyNames(obj).concat(getAllProps(Object.getPrototypeOf(obj))); return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
} }
// Given a string _expr_, returns all methods // Given a string _expr_, returns all methods
@@ -146,7 +151,11 @@ function getAllProps(obj) {
// e.g., expr="({ foo: null, bar: null, 4: null })" will // e.g., expr="({ foo: null, bar: null, 4: null })" will
// return ["foo", "bar", ...] but the list will not include "4", // return ["foo", "bar", ...] but the list will not include "4",
// since methods accessed with '.' notation must star with a letter or _. // since methods accessed with '.' notation must star with a letter or _.
function getPropertyNamesFromExpression(expr, commandHeader = '') { function getPropertyNamesFromExpression(expr, commandHeader) {
if (commandHeader == null) {
commandHeader = '';
}
let obj = {}; let obj = {};
if (!isUnsafeExpression(expr)) { if (!isUnsafeExpression(expr)) {
try { try {
@@ -159,14 +168,14 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
} }
let propsUnique = {}; let propsUnique = {};
if (typeof obj === 'object') { if (typeof obj === 'object'){
let allProps = getAllProps(obj); let allProps = getAllProps(obj);
// Get only things we are allowed to complete following a '.' // Get only things we are allowed to complete following a '.'
allProps = allProps.filter(isValidPropertyName); allProps = allProps.filter( isValidPropertyName );
// Make sure propsUnique contains one key for every // Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties // property so we end up with a unique list of properties
allProps.map(p => (propsUnique[p] = null)); allProps.map(p => propsUnique[p] = null);
} }
return Object.keys(propsUnique).sort(); return Object.keys(propsUnique).sort();
} }
@@ -183,26 +192,24 @@ function getCommonPrefix(words) {
return word; return word;
} }
// Remove any blocks that are quoted or are in a regex
function removeLiterals(str) {
if (str.length == 0)
return '';
let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') {
return removeLiterals(
str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') {
return removeLiterals(
str.slice(0, findMatchingSlash(str, str.length - 1)));
}
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
}
// Returns true if there is reason to think that eval(str) // Returns true if there is reason to think that eval(str)
// will modify the global scope // will modify the global scope
function isUnsafeExpression(str) { function isUnsafeExpression(str) {
// Remove any blocks that are quoted or are in a regex
function removeLiterals(str) {
if (str.length == 0) {
return '';
}
let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') {
return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') {
return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
}
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
}
// Check for any sort of assignment // Check for any sort of assignment
// The strategy used is dumb: remove any quotes // The strategy used is dumb: remove any quotes
@@ -210,10 +217,10 @@ function isUnsafeExpression(str) {
// If there is, it might be an unsafe assignment. // If there is, it might be an unsafe assignment.
let prunedStr = removeLiterals(str); let prunedStr = removeLiterals(str);
prunedStr = prunedStr.replace(/[=!]==/g, ''); // replace === and !== with nothing prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); // replace ==, <=, >=, != with nothing prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/[=]/)) { if (prunedStr.match(/=/)) {
return true; return true;
} else if (prunedStr.match(/;/)) { } else if (prunedStr.match(/;/)) {
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well // If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well
@@ -227,10 +234,10 @@ function isUnsafeExpression(str) {
function getDeclaredConstants(str) { function getDeclaredConstants(str) {
let ret = []; let ret = [];
str.split(';').forEach(s => { str.split(';').forEach(s => {
let base_, keyword; let base, keyword;
let match = s.match(/const\s+(\w+)\s*=/); let match = s.match(/const\s+(\w+)\s*=/);
if (match) { if (match) {
[base_, keyword] = match; [base, keyword] = match;
ret.push(keyword); ret.push(keyword);
} }
}); });

View File

@@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
const { GLib, GnomeDesktop, Meta } = imports.gi; const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Meta = imports.gi.Meta;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -61,7 +62,7 @@ var KeyboardManager = class {
this._currentKeymap.options == options) this._currentKeymap.options == options)
return; return;
this._currentKeymap = { layouts, variants, options }; this._currentKeymap = {layouts, variants, options};
Meta.get_backend().set_keymap(layouts, variants, options); Meta.get_backend().set_keymap(layouts, variants, options);
} }
@@ -126,7 +127,7 @@ var KeyboardManager = class {
_getLocaleLayout() { _getLocaleLayout() {
let locale = GLib.get_language_names()[0]; let locale = GLib.get_language_names()[0];
if (!locale.includes('_')) if (locale.indexOf('_') == -1)
locale = DEFAULT_LOCALE; locale = DEFAULT_LOCALE;
let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale); let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);

View File

@@ -1,7 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported canLock, getLoginManager, registerSessionWithGDM */
const { GLib, Gio } = imports.gi; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -44,39 +46,16 @@ function canLock() {
let version = result.deep_unpack()[0].deep_unpack(); let version = result.deep_unpack()[0].deep_unpack();
return haveSystemd() && versionCompare('3.5.91', version); return haveSystemd() && versionCompare('3.5.91', version);
} catch (e) { } catch(e) {
return false; return false;
} }
} }
function registerSessionWithGDM() {
log("Registering session with GDM");
Gio.DBus.system.call('org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null,
(source, result) => {
try {
source.call_finish(result);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log("Not calling RegisterSession(): method not exported, GDM too old?");
}
}
);
}
let _loginManager = null; let _loginManager = null;
/** /**
* getLoginManager: * LoginManager:
* An abstraction over systemd/logind and ConsoleKit. * An abstraction over systemd/logind and ConsoleKit.
* @returns {object} - the LoginManager singleton
* *
*/ */
function getLoginManager() { function getLoginManager() {
@@ -104,7 +83,7 @@ var LoginManagerSystemd = class {
getCurrentSessionProxy(callback) { getCurrentSessionProxy(callback) {
if (this._currentSession) { if (this._currentSession) {
callback(this._currentSession); callback (this._currentSession);
return; return;
} }
@@ -118,7 +97,7 @@ var LoginManagerSystemd = class {
} else { } else {
log('Failed to find "Display" session; are we the greeter?'); log('Failed to find "Display" session; are we the greeter?');
for ([session, objectPath] of this._userProxy.Sessions) { for (let [session, objectPath] of this._userProxy.Sessions) {
let sessionProxy = new SystemdLoginSession(Gio.DBus.system, let sessionProxy = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1', 'org.freedesktop.login1',
objectPath); objectPath);
@@ -184,10 +163,10 @@ var LoginManagerSystemd = class {
(proxy, result) => { (proxy, result) => {
let fd = -1; let fd = -1;
try { try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result); let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0]; fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd })); callback(new Gio.UnixInputStream({ fd: fd }));
} catch (e) { } catch(e) {
logError(e, "Error getting systemd inhibitor"); logError(e, "Error getting systemd inhibitor");
callback(null); callback(null);
} }
@@ -201,7 +180,7 @@ var LoginManagerSystemd = class {
Signals.addSignalMethods(LoginManagerSystemd.prototype); Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = class { var LoginManagerDummy = class {
getCurrentSessionProxy(_callback) { getCurrentSessionProxy(callback) {
// we could return a DummySession object that fakes whatever callers // we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal() // expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer // methods), but just never calling the callback should be safer

View File

@@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModemBase, ModemGsm, ModemCdma, BroadbandModem */
const { Gio, GObject, NM, NMA } = imports.gi; const Gio = imports.gi.Gio;
const NMA = imports.gi.NMA;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -26,33 +27,33 @@ function _getMobileProvidersDatabase() {
} }
// _findProviderForMccMnc: // _findProviderForMccMnc:
// @operatorName: operator name // @operator_name: operator name
// @operatorCode: operator code // @operator_code: operator code
// //
// Given an operator name string (which may not be a real operator name) and an // Given an operator name string (which may not be a real operator name) and an
// operator code string, tries to find a proper operator name to display. // operator code string, tries to find a proper operator name to display.
// //
function _findProviderForMccMnc(operatorName, operatorCode) { function _findProviderForMccMnc(operator_name, operator_code) {
if (operatorName) { if (operator_name) {
if (operatorName.length != 0 && if (operator_name.length != 0 &&
(operatorName.length > 6 || operatorName.length < 5)) { (operator_name.length > 6 || operator_name.length < 5)) {
// this looks like a valid name, i.e. not an MCCMNC (that some // this looks like a valid name, i.e. not an MCCMNC (that some
// devices return when not yet connected // devices return when not yet connected
return operatorName; return operator_name;
} }
if (isNaN(parseInt(operatorName))) { if (isNaN(parseInt(operator_name))) {
// name is definitely not a MCCMNC, so it may be a name // name is definitely not a MCCMNC, so it may be a name
// after all; return that // after all; return that
return operatorName; return operator_name;
} }
} }
let needle; let needle;
if ((!operatorName || operatorName.length == 0) && operatorCode) if ((!operator_name || operator_name.length == 0) && operator_code)
needle = operatorCode; needle = operator_code;
else if (operatorName && (operatorName.length == 6 || operatorName.length == 5)) else if (operator_name && (operator_name.length == 6 || operator_name.length == 5))
needle = operatorName; needle = operator_name;
else // nothing to search else // nothing to search
return null; return null;
@@ -71,7 +72,7 @@ function _findProviderForMccMnc(operatorName, operatorCode) {
// Tries to find the operator name corresponding to the given SID // Tries to find the operator name corresponding to the given SID
// //
function _findProviderForSid(sid) { function _findProviderForSid(sid) {
if (!sid) if (sid == 0)
return null; return null;
let mpd = _getMobileProvidersDatabase(); let mpd = _getMobileProvidersDatabase();
@@ -84,9 +85,9 @@ function _findProviderForSid(sid) {
} }
// ----------------------------------------------------- // //------------------------------------------------------------------------------
// Support for the old ModemManager interface (MM < 0.7) // // Support for the old ModemManager interface (MM < 0.7)
// ----------------------------------------------------- // //------------------------------------------------------------------------------
// The following are not the complete interfaces, just the methods we need // The following are not the complete interfaces, just the methods we need
@@ -98,46 +99,21 @@ const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInter
const ModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager.Modem.Cdma'); const ModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager.Modem.Cdma');
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface); const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
var ModemBase = GObject.registerClass({ var ModemGsm = class {
GTypeFlags: GObject.TypeFlags.ABSTRACT, constructor(path) {
Properties: {
'operator-name': GObject.ParamSpec.string(
'operator-name', 'operator-name', 'operator-name',
GObject.ParamFlags.READABLE,
null),
'signal-quality': GObject.ParamSpec.int(
'signal-quality', 'signal-quality', 'signal-quality',
GObject.ParamFlags.READABLE,
0, 100, 0),
},
}, class ModemBase extends GObject.Object {
_setOperatorName(operatorName) {
if (this.operator_name == operatorName)
return;
this.operator_name = operatorName;
this.notify('operator-name');
}
_setSignalQuality(signalQuality) {
if (this.signal_quality == signalQuality)
return;
this.signal_quality = signalQuality;
this.notify('signal-quality');
}
});
var ModemGsm = GObject.registerClass(
class ModemGsm extends ModemBase {
_init(path) {
super._init();
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path); this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
// Code is duplicated because the function have different signatures // Code is duplicated because the function have different signatures
this._proxy.connectSignal('SignalQuality', (proxy, sender, [quality]) => { this._proxy.connectSignal('SignalQuality', (proxy, sender, [quality]) => {
this._setSignalQuality(quality); this.signal_quality = quality;
this.emit('notify::signal-quality');
}); });
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [_status, code, name]) => { this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [status, code, name]) => {
this._setOperatorName(_findProviderForMccMnc(name, code)); this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
}); });
this._proxy.GetRegistrationInfoRemote(([result], err) => { this._proxy.GetRegistrationInfoRemote(([result], err) => {
if (err) { if (err) {
@@ -145,29 +121,33 @@ class ModemGsm extends ModemBase {
return; return;
} }
let [status_, code, name] = result; let [status, code, name] = result;
this._setOperatorName(_findProviderForMccMnc(name, code)); this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
}); });
this._proxy.GetSignalQualityRemote((result, err) => { this._proxy.GetSignalQualityRemote((result, err) => {
if (err) { if (err) {
// it will return an error if the device is not connected // it will return an error if the device is not connected
this._setSignalQuality(0); this.signal_quality = 0;
} else { } else {
let [quality] = result; let [quality] = result;
this._setSignalQuality(quality); this.signal_quality = quality;
} }
this.emit('notify::signal-quality');
}); });
} }
}); };
Signals.addSignalMethods(ModemGsm.prototype);
var ModemCdma = GObject.registerClass( var ModemCdma = class {
class ModemCdma extends ModemBase { constructor(path) {
_init(path) {
super._init();
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path); this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
this._proxy.connectSignal('SignalQuality', (proxy, sender, params) => { this._proxy.connectSignal('SignalQuality', (proxy, sender, params) => {
this._setSignalQuality(params[0]); this.signal_quality = params[0];
this.emit('notify::signal-quality');
// receiving this signal means the device got activated // receiving this signal means the device got activated
// and we can finally call GetServingSystem // and we can finally call GetServingSystem
@@ -177,11 +157,12 @@ class ModemCdma extends ModemBase {
this._proxy.GetSignalQualityRemote((result, err) => { this._proxy.GetSignalQualityRemote((result, err) => {
if (err) { if (err) {
// it will return an error if the device is not connected // it will return an error if the device is not connected
this._setSignalQuality(0); this.signal_quality = 0;
} else { } else {
let [quality] = result; let [quality] = result;
this._setSignalQuality(quality); this.signal_quality = quality;
} }
this.emit('notify::signal-quality');
}); });
} }
@@ -189,19 +170,22 @@ class ModemCdma extends ModemBase {
this._proxy.GetServingSystemRemote(([result], err) => { this._proxy.GetServingSystemRemote(([result], err) => {
if (err) { if (err) {
// it will return an error if the device is not connected // it will return an error if the device is not connected
this._setOperatorName(null); this.operator_name = null;
} else { } else {
let [bandClass_, band_, sid] = result; let [bandClass, band, sid] = result;
this._setOperatorName(_findProviderForSid(sid));
this.operator_name = _findProviderForSid(sid)
} }
this.emit('notify::operator-name');
}); });
} }
}); };
Signals.addSignalMethods(ModemCdma.prototype);
// ------------------------------------------------------- // //------------------------------------------------------------------------------
// Support for the new ModemManager1 interface (MM >= 0.7) // // Support for the new ModemManager1 interface (MM >= 0.7)
// ------------------------------------------------------- // //------------------------------------------------------------------------------
const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem'); const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem');
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface); const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
@@ -212,20 +196,12 @@ const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gp
const BroadbandModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem.ModemCdma'); const BroadbandModemCdmaInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem.ModemCdma');
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface); const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
var BroadbandModem = GObject.registerClass({ var BroadbandModem = class {
Properties: { constructor(path, capabilities) {
'capabilities': GObject.ParamSpec.flags( this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
'capabilities', 'capabilities', 'capabilities',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
NM.DeviceModemCapabilities.$gtype,
NM.DeviceModemCapabilities.NONE),
},
}, class BroadbandModem extends ModemBase {
_init(path, capabilities) {
super._init({ capabilities });
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path); this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path); this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._capabilities = capabilities;
this._proxy.connect('g-properties-changed', (proxy, properties) => { this._proxy.connect('g-properties-changed', (proxy, properties) => {
if ('SignalQuality' in properties.deep_unpack()) if ('SignalQuality' in properties.deep_unpack())
@@ -249,22 +225,24 @@ var BroadbandModem = GObject.registerClass({
} }
_reloadSignalQuality() { _reloadSignalQuality() {
let [quality, recent_] = this.SignalQuality; let [quality, recent] = this._proxy.SignalQuality;
this._setSignalQuality(quality); this.signal_quality = quality;
this.emit('notify::signal-quality');
} }
_reloadOperatorName() { _reloadOperatorName() {
let newName = ""; let new_name = "";
if (this.operator_name_3gpp && this.operator_name_3gpp.length > 0) if (this.operator_name_3gpp && this.operator_name_3gpp.length > 0)
newName += this.operator_name_3gpp; new_name += this.operator_name_3gpp;
if (this.operator_name_cdma && this.operator_name_cdma.length > 0) { if (this.operator_name_cdma && this.operator_name_cdma.length > 0) {
if (newName != "") if (new_name != "")
newName += ", "; new_name += ", ";
newName += this.operator_name_cdma; new_name += this.operator_name_cdma;
} }
this._setOperatorName(newName); this.operator_name = new_name;
this.emit('notify::operator-name');
} }
_reload3gppOperatorName() { _reload3gppOperatorName() {
@@ -279,4 +257,5 @@ var BroadbandModem = GObject.registerClass({
this.operator_name_cdma = _findProviderForSid(sid); this.operator_name_cdma = _findProviderForSid(sid);
this._reloadOperatorName(); this._reloadOperatorName();
} }
}); };
Signals.addSignalMethods(BroadbandModem.prototype);

View File

@@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Gio, GLib } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Params = imports.misc.params; const Params = imports.misc.params;
const Signals = imports.signals; const Signals = imports.signals;
@@ -89,11 +90,14 @@ var ObjectManager = class {
g_interface_info: info, g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START }); g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => { proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
(initable, result) => {
let error = null;
try { try {
initable.init_finish(result); initable.init_finish(result);
} catch (e) { } catch(e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`); logError(e, 'could not initialize proxy for interface ' + interfaceName);
if (onFinished) if (onFinished)
onFinished(); onFinished();
@@ -152,10 +156,11 @@ var ObjectManager = class {
} }
_onManagerProxyLoaded(initable, result) { _onManagerProxyLoaded(initable, result) {
let error = null;
try { try {
initable.init_finish(result); initable.init_finish(result);
} catch (e) { } catch(e) {
logError(e, `could not initialize object manager for object ${this._serviceName}`); logError(e, 'could not initialize object manager for object ' + params.name);
this._tryToCompleteLoad(); this._tryToCompleteLoad();
return; return;
@@ -192,8 +197,9 @@ var ObjectManager = class {
_onNameAppeared() { _onNameAppeared() {
this._managerProxy.GetManagedObjectsRemote((result, error) => { this._managerProxy.GetManagedObjectsRemote((result, error) => {
if (!result) { if (!result) {
if (error) if (error) {
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`); logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
}
this._tryToCompleteLoad(); this._tryToCompleteLoad();
return; return;
@@ -275,8 +281,8 @@ var ObjectManager = class {
let object = this._objects[objectPaths]; let object = this._objects[objectPaths];
let interfaceNames = Object.keys(object); let interfaceNames = Object.keys(object);
for (let j = 0; j < interfaceNames.length; j++) { for (let j = 0; i < interfaceNames.length; i++) {
let interfaceName = interfaceNames[j]; let interfaceName = interfaceNames[i];
if (object[interfaceName]) if (object[interfaceName])
proxies.push(object(interfaceName)); proxies.push(object(interfaceName));
} }

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported parse */
// parse: // parse:
// @params: caller-provided parameter object, or %null // @params: caller-provided parameter object, or %null
@@ -15,14 +14,22 @@
// //
// Return value: a new object, containing the merged parameters from // Return value: a new object, containing the merged parameters from
// @params and @defaults // @params and @defaults
function parse(params = {}, defaults, allowExtras) { function parse(params, defaults, allowExtras) {
if (!allowExtras) { let ret = {}, prop;
for (let prop in params) {
if (!(prop in defaults)) if (!params)
throw new Error(`Unrecognized parameter "${prop}"`); params = {};
}
for (prop in params) {
if (!(prop in defaults) && !allowExtras)
throw new Error('Unrecognized parameter "' + prop + '"');
ret[prop] = params[prop];
} }
let defaultsCopy = Object.assign({}, defaults); for (prop in defaults) {
return Object.assign(defaultsCopy, params); if (!(prop in params))
ret[prop] = defaults[prop];
}
return ret;
} }

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PermissionStore */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
@@ -13,4 +12,4 @@ function PermissionStore(initCallback, cancellable) {
'org.freedesktop.impl.portal.PermissionStore', 'org.freedesktop.impl.portal.PermissionStore',
'/org/freedesktop/impl/portal/PermissionStore', '/org/freedesktop/impl/portal/PermissionStore',
initCallback, cancellable); initCallback, cancellable);
} };

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getSmartcardManager */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager; const ObjectManager = imports.misc.objectManager;
@@ -30,7 +30,7 @@ var SmartcardManager = class {
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session, this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
name: "org.gnome.SettingsDaemon.Smartcard", name: "org.gnome.SettingsDaemon.Smartcard",
objectPath: '/org/gnome/SettingsDaemon/Smartcard', objectPath: '/org/gnome/SettingsDaemon/Smartcard',
knownInterfaces: [SmartcardTokenIface], knownInterfaces: [ SmartcardTokenIface ],
onLoaded: this._onLoaded.bind(this) }); onLoaded: this._onLoaded.bind(this) });
this._insertedTokens = {}; this._insertedTokens = {};
this._loginToken = null; this._loginToken = null;
@@ -72,11 +72,12 @@ var SmartcardManager = class {
if ('IsInserted' in properties.deep_unpack()) { if ('IsInserted' in properties.deep_unpack()) {
this._updateToken(token); this._updateToken(token);
if (token.IsInserted) if (token.IsInserted) {
this.emit('smartcard-inserted', token); this.emit('smartcard-inserted', token);
else } else {
this.emit('smartcard-removed', token); this.emit('smartcard-removed', token);
} }
}
}); });
// Emit a smartcard-inserted at startup if it's already plugged in // Emit a smartcard-inserted at startup if it's already plugged in

View File

@@ -1,5 +1,10 @@
/* exported getDefault */ const AccountsService = imports.gi.AccountsService;
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi; const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const GObject = imports.gi.GObject;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const LoginManager = imports.misc.loginManager; const LoginManager = imports.misc.loginManager;
@@ -74,8 +79,8 @@ const SystemActions = GObject.registerClass({
'orientation-lock-icon', 'orientation-lock-icon',
'orientation-lock-icon', 'orientation-lock-icon',
GObject.ParamFlags.READWRITE, GObject.ParamFlags.READWRITE,
null), null)
}, }
}, class SystemActions extends GObject.Object { }, class SystemActions extends GObject.Object {
_init() { _init() {
super._init(); super._init();
@@ -84,54 +89,48 @@ const SystemActions = GObject.registerClass({
this._canHaveSuspend = true; this._canHaveSuspend = true;
this._actions = new Map(); this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID, { this._actions.set(POWER_OFF_ACTION_ID,
// Translators: The name of the power-off action in search { // Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"), name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic', iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons // Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _("power off;shutdown;reboot;restart").split(/[; ]/), keywords: _("power off;shutdown;reboot;restart").split(';'),
available: false, available: false });
}); this._actions.set(LOCK_SCREEN_ACTION_ID,
this._actions.set(LOCK_SCREEN_ACTION_ID, { { // Translators: The name of the lock screen action in search
// Translators: The name of the lock screen action in search
name: C_("search-result", "Lock Screen"), name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic', iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons // Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(/[; ]/), keywords: _("lock screen").split(';'),
available: false, available: false });
}); this._actions.set(LOGOUT_ACTION_ID,
this._actions.set(LOGOUT_ACTION_ID, { { // Translators: The name of the logout action in search
// Translators: The name of the logout action in search
name: C_("search-result", "Log Out"), name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic', iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons // Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;log out;sign off").split(/[; ]/), keywords: _("logout;sign off").split(';'),
available: false, available: false });
}); this._actions.set(SUSPEND_ACTION_ID,
this._actions.set(SUSPEND_ACTION_ID, { { // Translators: The name of the suspend action in search
// Translators: The name of the suspend action in search
name: C_("search-result", "Suspend"), name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic', iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons // Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/), keywords: _("suspend;sleep").split(';'),
available: false, available: false });
}); this._actions.set(SWITCH_USER_ACTION_ID,
this._actions.set(SWITCH_USER_ACTION_ID, { { // Translators: The name of the switch user action in search
// Translators: The name of the switch user action in search
name: C_("search-result", "Switch User"), name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic', iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons // Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(/[; ]/), keywords: _("switch user").split(';'),
available: false, available: false });
}); this._actions.set(LOCK_ORIENTATION_ACTION_ID,
this._actions.set(LOCK_ORIENTATION_ACTION_ID, { { // Translators: The name of the lock orientation action in search
// Translators: The name of the lock orientation action in search
name: C_("search-result", "Lock Orientation"), name: C_("search-result", "Lock Orientation"),
iconName: '', iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons // Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;screen;rotation").split(/[; ]/), keywords: _("lock orientation;screen;rotation").split(';'),
available: false, available: false });
});
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
@@ -144,99 +143,94 @@ const SystemActions = GObject.registerClass({
this._userManager = AccountsService.UserManager.get_default(); this._userManager = AccountsService.UserManager.get_default();
this._userManager.connect('notify::is-loaded', this._userManager.connect('notify::is-loaded',
() => this._updateMultiUser()); () => { this._updateMultiUser(); });
this._userManager.connect('notify::has-multiple-users', this._userManager.connect('notify::has-multiple-users',
() => this._updateMultiUser()); () => { this._updateMultiUser(); });
this._userManager.connect('user-added', this._userManager.connect('user-added',
() => this._updateMultiUser()); () => { this._updateMultiUser(); });
this._userManager.connect('user-removed', this._userManager.connect('user-removed',
() => this._updateMultiUser()); () => { this._updateMultiUser(); });
this._lockdownSettings.connect(`changed::${DISABLE_USER_SWITCH_KEY}`, this._lockdownSettings.connect('changed::' + DISABLE_USER_SWITCH_KEY,
() => this._updateSwitchUser()); () => { this._updateSwitchUser(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`, this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
() => this._updateLogout()); () => { this._updateLogout(); });
global.settings.connect(`changed::${ALWAYS_SHOW_LOG_OUT_KEY}`, global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
() => this._updateLogout()); () => { this._updateLogout(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOCK_SCREEN_KEY}`, this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
() => this._updateLockScreen()); () => { this._updateLockScreen(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`, this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
() => this._updateHaveShutdown()); () => { this._updateHaveShutdown(); });
this.forceUpdate(); this.forceUpdate();
this._orientationSettings.connect('changed::orientation-lock', this._orientationSettings.connect('changed::orientation-lock',
() => { () => { this._updateOrientationLock();
this._updateOrientationLock(); this._updateOrientationLockIcon(); });
this._updateOrientationLockIcon();
});
Main.layoutManager.connect('monitors-changed', Main.layoutManager.connect('monitors-changed',
() => this._updateOrientationLock()); () => { this._updateOrientationLock(); });
this._sensorProxy = new SensorProxy(Gio.DBus.system, Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
SENSOR_BUS_NAME, Gio.BusNameWatcherFlags.NONE,
SENSOR_OBJECT_PATH, () => { this._sensorProxyAppeared(); },
(proxy, error) => { () => {
if (error) this._sensorProxy = null;
log(error.message);
},
null,
Gio.DBusProxyFlags.DO_NOT_AUTO_START);
this._sensorProxy.connect('g-properties-changed', () => {
this._updateOrientationLock();
});
this._sensorProxy.connect('notify::g-name-owner', () => {
this._updateOrientationLock(); this._updateOrientationLock();
}); });
this._updateOrientationLock(); this._updateOrientationLock();
this._updateOrientationLockIcon(); this._updateOrientationLockIcon();
Main.sessionMode.connect('updated', () => this._sessionUpdated()); Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
this._sessionUpdated(); this._sessionUpdated();
} }
// eslint-disable-next-line camelcase
get can_power_off() { get can_power_off() {
return this._actions.get(POWER_OFF_ACTION_ID).available; return this._actions.get(POWER_OFF_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_suspend() { get can_suspend() {
return this._actions.get(SUSPEND_ACTION_ID).available; return this._actions.get(SUSPEND_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_lock_screen() { get can_lock_screen() {
return this._actions.get(LOCK_SCREEN_ACTION_ID).available; return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_switch_user() { get can_switch_user() {
return this._actions.get(SWITCH_USER_ACTION_ID).available; return this._actions.get(SWITCH_USER_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_logout() { get can_logout() {
return this._actions.get(LOGOUT_ACTION_ID).available; return this._actions.get(LOGOUT_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get can_lock_orientation() { get can_lock_orientation() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available; return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
} }
// eslint-disable-next-line camelcase
get orientation_lock_icon() { get orientation_lock_icon() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName; return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
} }
_sensorProxyAppeared() {
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._sensorProxy.connect('g-properties-changed',
() => { this._updateOrientationLock(); });
this._updateOrientationLock();
});
}
_updateOrientationLock() { _updateOrientationLock() {
let available = false; let available = false;
if (this._sensorProxy.g_name_owner) { if (this._sensorProxy)
available = this._sensorProxy.HasAccelerometer && available = this._sensorProxy.HasAccelerometer &&
this._monitorManager.get_is_builtin_display_on(); this._monitorManager.get_is_builtin_display_on();
}
this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available; this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available;
@@ -245,8 +239,7 @@ const SystemActions = GObject.registerClass({
_updateOrientationLockIcon() { _updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock'); let locked = this._orientationSettings.get_boolean('orientation-lock');
let iconName = locked let iconName = locked ? 'rotation-locked-symbolic'
? 'rotation-locked-symbolic'
: 'rotation-allowed-symbolic'; : 'rotation-allowed-symbolic';
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName; this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
@@ -270,14 +263,13 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) { getMatchingActions(terms) {
// terms is a list of strings // terms is a list of strings
terms = terms.map(term => term.toLowerCase()); terms = terms.map((term) => { return term.toLowerCase(); });
let results = []; let results = [];
for (let [key, { available, keywords }] of this._actions) { for (let [key, {available, keywords}] of this._actions)
if (available && terms.every(t => keywords.some(k => k.startsWith(t)))) if (available && terms.every(t => keywords.some(k => (k.indexOf(t) >= 0))))
results.push(key); results.push(key);
}
return results; return results;
} }

View File

@@ -1,23 +1,28 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView, wiggle */
const { Clutter, Gio, GLib, GObject, Shell, St, GnomeDesktop } = imports.gi; const Clutter = imports.gi.Clutter;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Params = imports.misc.params; const Params = imports.misc.params;
var SCROLL_TIME = 100; var SCROLL_TIME = 0.1;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls // http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\([^\\s()<>]+\\)'; const _balancedParens = '\\([^\\s()<>]+\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]'; const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u200E\u200F\u201C\u201D\u2018\u2019\u202A\u202C]'; const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _urlRegexp = new RegExp( const _urlRegexp = new RegExp(
`(^|${_leadingJunk})` + '(^|' + _leadingJunk + ')' +
'(' + '(' +
'(?:' + '(?:' +
'(?:http|https|ftp)://' + // scheme:// '(?:http|https|ftp)://' + // scheme://
@@ -29,12 +34,12 @@ const _urlRegexp = new RegExp(
'(?:' + // one or more: '(?:' + // one or more:
'[^\\s()<>]+' + // run of non-space non-() '[^\\s()<>]+' + // run of non-space non-()
'|' + // or '|' + // or
`${_balancedParens}` + // balanced parens _balancedParens + // balanced parens
')+' + ')+' +
'(?:' + // end with: '(?:' + // end with:
`${_balancedParens}` + // balanced parens _balancedParens + // balanced parens
'|' + // or '|' + // or
`${_notTrailingJunk}` + // last non-junk char _notTrailingJunk + // last non-junk char
')' + ')' +
')', 'gi'); ')', 'gi');
@@ -69,16 +74,16 @@ function spawn(argv) {
} }
// spawnCommandLine: // spawnCommandLine:
// @commandLine: a command line // @command_line: a command line
// //
// Runs @commandLine in the background, handling any errors that // Runs @command_line in the background, handling any errors that
// occur when trying to parse or start the program. // occur when trying to parse or start the program.
function spawnCommandLine(commandLine) { function spawnCommandLine(command_line) {
try { try {
let [success_, argv] = GLib.shell_parse_argv(commandLine); let [success, argv] = GLib.shell_parse_argv(command_line);
trySpawn(argv); trySpawn(argv);
} catch (err) { } catch (err) {
_handleSpawnError(commandLine, err); _handleSpawnError(command_line, err);
} }
} }
@@ -93,7 +98,7 @@ function spawnApp(argv) {
let context = global.create_app_launch_context(0, -1); let context = global.create_app_launch_context(0, -1);
app.launch([], context); app.launch([], context);
} catch (err) { } catch(err) {
_handleSpawnError(argv[0], err); _handleSpawnError(argv[0], err);
} }
} }
@@ -103,10 +108,11 @@ function spawnApp(argv) {
// //
// Runs @argv in the background. If launching @argv fails, // Runs @argv in the background. If launching @argv fails,
// this will throw an error. // this will throw an error.
function trySpawn(argv) { function trySpawn(argv)
var success_, pid; {
var success, pid;
try { try {
[success_, pid] = GLib.spawn_async(null, argv, null, [success, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null); null);
} catch (err) { } catch (err) {
@@ -121,15 +127,12 @@ function trySpawn(argv) {
// We are only interested in the part in the parentheses. (And // We are only interested in the part in the parentheses. (And
// we can't pattern match the text, since it gets localized.) // we can't pattern match the text, since it gets localized.)
let message = err.message.replace(/.*\((.+)\)/, '$1'); let message = err.message.replace(/.*\((.+)\)/, '$1');
throw new err.constructor({ code: err.code, message }); throw new (err.constructor)({ code: err.code,
message: message });
} else { } else {
throw err; throw err;
} }
} }
// Async call, we don't need the reply though
GnomeDesktop.start_systemd_scope(argv[0], pid, null, null, null, () => {});
// Dummy child watch; we don't want to double-fork internally // Dummy child watch; we don't want to double-fork internally
// because then we lose the parent-child relationship, which // because then we lose the parent-child relationship, which
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275 // can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
@@ -137,19 +140,19 @@ function trySpawn(argv) {
} }
// trySpawnCommandLine: // trySpawnCommandLine:
// @commandLine: a command line // @command_line: a command line
// //
// Runs @commandLine in the background. If launching @commandLine // Runs @command_line in the background. If launching @command_line
// fails, this will throw an error. // fails, this will throw an error.
function trySpawnCommandLine(commandLine) { function trySpawnCommandLine(command_line) {
let success_, argv; let success, argv;
try { try {
[success_, argv] = GLib.shell_parse_argv(commandLine); [success, argv] = GLib.shell_parse_argv(command_line);
} catch (err) { } catch (err) {
// Replace "Error invoking GLib.shell_parse_argv: " with // Replace "Error invoking GLib.shell_parse_argv: " with
// something nicer // something nicer
err.message = err.message.replace(/[^:]*: /, `${_("Could not parse command:")}\n`); err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
throw err; throw err;
} }
@@ -175,28 +178,23 @@ function formatTimeSpan(date) {
if (minutesAgo < 5) if (minutesAgo < 5)
return _("Just now"); return _("Just now");
if (hoursAgo < 1) { if (hoursAgo < 1)
return Gettext.ngettext("%d minute ago", return Gettext.ngettext("%d minute ago",
"%d minutes ago", minutesAgo).format(minutesAgo); "%d minutes ago", minutesAgo).format(minutesAgo);
} if (daysAgo < 1)
if (daysAgo < 1) {
return Gettext.ngettext("%d hour ago", return Gettext.ngettext("%d hour ago",
"%d hours ago", hoursAgo).format(hoursAgo); "%d hours ago", hoursAgo).format(hoursAgo);
}
if (daysAgo < 2) if (daysAgo < 2)
return _("Yesterday"); return _("Yesterday");
if (daysAgo < 15) { if (daysAgo < 15)
return Gettext.ngettext("%d day ago", return Gettext.ngettext("%d day ago",
"%d days ago", daysAgo).format(daysAgo); "%d days ago", daysAgo).format(daysAgo);
} if (weeksAgo < 8)
if (weeksAgo < 8) {
return Gettext.ngettext("%d week ago", return Gettext.ngettext("%d week ago",
"%d weeks ago", weeksAgo).format(weeksAgo); "%d weeks ago", weeksAgo).format(weeksAgo);
} if (yearsAgo < 1)
if (yearsAgo < 1) {
return Gettext.ngettext("%d month ago", return Gettext.ngettext("%d month ago",
"%d months ago", monthsAgo).format(monthsAgo); "%d months ago", monthsAgo).format(monthsAgo);
}
return Gettext.ngettext("%d year ago", return Gettext.ngettext("%d year ago",
"%d years ago", yearsAgo).format(yearsAgo); "%d years ago", yearsAgo).format(yearsAgo);
} }
@@ -221,10 +219,7 @@ function formatTime(time, params) {
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); _desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
let clockFormat = _desktopSettings.get_string('clock-format'); let clockFormat = _desktopSettings.get_string('clock-format');
params = Params.parse(params, { params = Params.parse(params, { timeOnly: false });
timeOnly: false,
ampm: true,
});
if (clockFormat == '24h') { if (clockFormat == '24h') {
// Show only the time if date is on today // Show only the time if date is on today
@@ -232,7 +227,7 @@ function formatTime(time, params) {
/* Translators: Time in 24h format */ /* Translators: Time in 24h format */
format = N_("%H\u2236%M"); format = N_("%H\u2236%M");
// Show the word "Yesterday" and time if date is on yesterday // Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo < 2) else if (daysAgo <2)
/* Translators: this is the word "Yesterday" followed by a /* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */ time string in 24h format. i.e. "Yesterday, 14:30" */
// xgettext:no-c-format // xgettext:no-c-format
@@ -257,11 +252,11 @@ function formatTime(time, params) {
format = N_("%B %-d %Y, %H\u2236%M"); format = N_("%B %-d %Y, %H\u2236%M");
} else { } else {
// Show only the time if date is on today // Show only the time if date is on today
if (daysAgo < 1 || params.timeOnly) // eslint-disable-line no-lonely-if if (daysAgo < 1 || params.timeOnly)
/* Translators: Time in 12h format */ /* Translators: Time in 12h format */
format = N_("%l\u2236%M %p"); format = N_("%l\u2236%M %p");
// Show the word "Yesterday" and time if date is on yesterday // Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo < 2) else if (daysAgo <2)
/* Translators: this is the word "Yesterday" followed by a /* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */ time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format // xgettext:no-c-format
@@ -286,11 +281,6 @@ function formatTime(time, params) {
format = N_("%B %-d %Y, %l\u2236%M %p"); format = N_("%B %-d %Y, %l\u2236%M %p");
} }
// Time in short 12h format, without the equivalent of "AM" or "PM"; used
// when it is clear from the context
if (!params.ampm)
format = format.replace(/\s*%p/g, '');
let formattedTime = date.format(Shell.util_translate_time_string(format)); let formattedTime = date.format(Shell.util_translate_time_string(format));
// prepend LTR-mark to colon/ratio to force a text direction on times // prepend LTR-mark to colon/ratio to force a text direction on times
return formattedTime.replace(/([:\u2236])/g, '\u200e$1'); return formattedTime.replace(/([:\u2236])/g, '\u200e$1');
@@ -304,7 +294,7 @@ function createTimeLabel(date, params) {
let id = _desktopSettings.connect('changed::clock-format', () => { let id = _desktopSettings.connect('changed::clock-format', () => {
label.text = formatTime(date, params); label.text = formatTime(date, params);
}); });
label.connect('destroy', () => _desktopSettings.disconnect(id)); label.connect('destroy', () => { _desktopSettings.disconnect(id); });
return label; return label;
} }
@@ -329,8 +319,7 @@ function lowerBound(array, val, cmp) {
if (array.length == 0) if (array.length == 0)
return 0; return 0;
min = 0; min = 0; max = array.length;
max = array.length;
while (min < (max - 1)) { while (min < (max - 1)) {
mid = Math.floor((min + max) / 2); mid = Math.floor((min + max) / 2);
v = cmp(array[mid], val); v = cmp(array[mid], val);
@@ -341,7 +330,7 @@ function lowerBound(array, val, cmp) {
max = mid; max = mid;
} }
return min == max || cmp(array[min], val) < 0 ? max : min; return (min == max || cmp(array[min], val) < 0) ? max : min;
} }
// insertSorted: // insertSorted:
@@ -362,13 +351,19 @@ function insertSorted(array, val, cmp) {
var CloseButton = GObject.registerClass( var CloseButton = GObject.registerClass(
class CloseButton extends St.Button { class CloseButton extends St.Button {
_init(boxpointer) { _init(boxpointer) {
super._init({ super._init({ style_class: 'notification-close'});
style_class: 'notification-close',
x_expand: true, // This is a bit tricky. St.Bin has its own x-align/y-align properties
y_expand: true, // that compete with Clutter's properties. This should be fixed for
x_align: Clutter.ActorAlign.END, // Clutter 2.0. Since St.Bin doesn't define its own setters, the
y_align: Clutter.ActorAlign.START, // setters are a workaround to get Clutter's version.
}); this.set_x_align(Clutter.ActorAlign.END);
this.set_y_align(Clutter.ActorAlign.START);
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
// to respect the alignments.
this.set_x_expand(true);
this.set_y_expand(true);
this._boxPointer = boxpointer; this._boxPointer = boxpointer;
if (boxpointer) if (boxpointer)
@@ -376,7 +371,7 @@ class CloseButton extends St.Button {
} }
_computeBoxPointerOffset() { _computeBoxPointerOffset() {
if (!this._boxPointer || !this._boxPointer.get_stage()) if (!this._boxPointer || !this._boxPointer.actor.get_stage())
return 0; return 0;
let side = this._boxPointer.arrowSide; let side = this._boxPointer.arrowSide;
@@ -390,7 +385,7 @@ class CloseButton extends St.Button {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let offY = this._computeBoxPointerOffset(); let offY = this._computeBoxPointerOffset();
this.translation_x = themeNode.get_length('-shell-close-overlap-x'); this.translation_x = themeNode.get_length('-shell-close-overlap-x')
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY; this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
} }
@@ -406,7 +401,7 @@ function makeCloseButton(boxpointer) {
function ensureActorVisibleInScrollView(scrollView, actor) { function ensureActorVisibleInScrollView(scrollView, actor) {
let adjustment = scrollView.vscroll.adjustment; let adjustment = scrollView.vscroll.adjustment;
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values(); let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let offset = 0; let offset = 0;
let vfade = scrollView.get_effect("fade"); let vfade = scrollView.get_effect("fade");
@@ -421,7 +416,7 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
if (!parent) if (!parent)
throw new Error("actor not in scroll view"); throw new Error("actor not in scroll view");
box = parent.get_allocation_box(); let box = parent.get_allocation_box();
y1 += box.y1; y1 += box.y1;
y2 += box.y1; y2 += box.y1;
parent = parent.get_parent(); parent = parent.get_parent();
@@ -434,42 +429,97 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
else else
return; return;
adjustment.ease(value, { Tweener.addTween(adjustment,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, { value: value,
duration: SCROLL_TIME, time: SCROLL_TIME,
}); transition: 'easeOutQuad' });
} }
function wiggle(actor, params) { var AppSettingsMonitor = class {
params = Params.parse(params, { constructor(appId, schemaId) {
offset: 0, this._appId = appId;
duration: 0, this._schemaId = schemaId;
wiggleCount: 0,
});
actor.translation_x = 0;
// Accelerate before wiggling this._app = null;
actor.ease({ this._settings = null;
translation_x: -params.offset, this._handlers = [];
duration: params.duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, this._schemaSource = Gio.SettingsSchemaSource.get_default();
onComplete: () => {
// Wiggle this._appSystem = Shell.AppSystem.get_default();
actor.ease({ this._appSystem.connect('installed-changed',
translation_x: params.offset, this._onInstalledChanged.bind(this));
duration: params.duration, this._onInstalledChanged();
mode: Clutter.AnimationMode.LINEAR, }
repeatCount: params.wiggleCount,
autoReverse: true, get available() {
onComplete: () => { return this._app != null && this._settings != null;
// Decelerate and return to the original position }
actor.ease({
translation_x: 0, activateApp() {
duration: params.duration, if (this._app)
mode: Clutter.AnimationMode.EASE_IN_QUAD, this._app.activate();
}
watchSetting(key, callback) {
let handler = { id: 0, key: key, callback: callback };
this._handlers.push(handler);
this._connectHandler(handler);
}
_connectHandler(handler) {
if (!this._settings || handler.id > 0)
return;
handler.id = this._settings.connect('changed::' + handler.key,
handler.callback);
handler.callback(this._settings, handler.key);
}
_disconnectHandler(handler) {
if (this._settings && handler.id > 0)
this._settings.disconnect(handler.id);
handler.id = 0;
}
_onInstalledChanged() {
let hadApp = (this._app != null);
this._app = this._appSystem.lookup_app(this._appId);
let haveApp = (this._app != null);
if (hadApp == haveApp)
return;
if (haveApp)
this._checkSettings();
else
this._setSettings(null);
}
_setSettings(settings) {
this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
let hadSettings = (this._settings != null);
this._settings = settings;
let haveSettings = (this._settings != null);
this._handlers.forEach((handler) => { this._connectHandler(handler); });
if (hadSettings != haveSettings)
this.emit('available-changed');
}
_checkSettings() {
let schema = this._schemaSource.lookup(this._schemaId, true);
if (schema) {
this._setSettings(new Gio.Settings({ settings_schema: schema }));
} else if (this._app) {
Mainloop.timeout_add_seconds(1, () => {
this._checkSettings();
return GLib.SOURCE_REMOVE;
}); });
}, }
}); }
}, };
}); Signals.addSignalMethods(AppSettingsMonitor.prototype);
}

View File

@@ -1,19 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi; const Geoclue = imports.gi.Geoclue;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GWeather = imports.gi.GWeather;
const Signals = imports.signals; const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore; const PermissionStore = imports.misc.permissionStore;
const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
const WEATHER_BUS_NAME = 'org.gnome.Weather';
const WEATHER_OBJECT_PATH = '/org/gnome/Weather';
const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration';
const WEATHER_APP_ID = 'org.gnome.Weather.desktop';
// Minimum time between updates to show loading indication // Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE; var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
@@ -32,27 +26,18 @@ var WeatherClient = class {
this._gclueStarting = false; this._gclueStarting = false;
this._gclueLocationChangedId = 0; this._gclueLocationChangedId = 0;
this._needsAuth = true;
this._weatherAuthorized = false; this._weatherAuthorized = false;
this._permStore = new PermissionStore.PermissionStore((proxy, error) => { this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
if (error) { if (error) {
log(`Failed to connect to permissionStore: ${error.message}`); log('Failed to connect to permissionStore: ' + error.message);
return; return;
} }
if (this._permStore.g_name_owner == null) { this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
// Failed to auto-start, likely because xdg-desktop-portal if (error)
// isn't installed; don't restrict access to location service log('Error looking up permission: ' + error.message);
this._weatherAuthorized = true;
this._updateAutoLocation();
return;
}
this._permStore.LookupRemote('gnome', 'geolocation', (res, err) => { let [perms, data] = error ? [{}, null] : res;
if (err)
log(`Error looking up permission: ${err.message}`);
let [perms, data] = err ? [{}, null] : res;
let params = ['gnome', 'geolocation', false, data, perms]; let params = ['gnome', 'geolocation', false, data, perms];
this._onPermStoreChanged(this._permStore, '', params); this._onPermStoreChanged(this._permStore, '', params);
}); });
@@ -76,38 +61,17 @@ var WeatherClient = class {
this.emit('changed'); this.emit('changed');
}); });
this._weatherApp = null; this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
this._weatherProxy = null; 'org.gnome.Weather.Application');
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface); this._weatherAppMon.watchSetting('automatic-location',
Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null,
this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather',
});
this._settings.connect('changed::automatic-location',
this._onAutomaticLocationChanged.bind(this)); this._onAutomaticLocationChanged.bind(this));
this._onAutomaticLocationChanged(); this._weatherAppMon.watchSetting('locations',
this._settings.connect('changed::locations',
this._onLocationsChanged.bind(this)); this._onLocationsChanged.bind(this));
this._onLocationsChanged();
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
} }
get available() { get available() {
return this._weatherApp != null; return this._weatherAppMon.available;
} }
get loading() { get loading() {
@@ -123,8 +87,7 @@ var WeatherClient = class {
} }
activateApp() { activateApp() {
if (this._weatherApp) this._weatherAppMon.activateApp();
this._weatherApp.activate();
} }
update() { update() {
@@ -143,46 +106,7 @@ var WeatherClient = class {
get _useAutoLocation() { get _useAutoLocation() {
return this._autoLocationRequested && return this._autoLocationRequested &&
this._locationSettings.get_boolean('enabled') && this._locationSettings.get_boolean('enabled') &&
(!this._needsAuth || this._weatherAuthorized); this._weatherAuthorized;
}
_onWeatherProxyReady(o, res) {
try {
this._weatherProxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log(`Failed to create GNOME Weather proxy: ${e}`);
return;
}
this._weatherProxy.connect('g-properties-changed',
this._onWeatherPropertiesChanged.bind(this));
this._onWeatherPropertiesChanged();
}
_onWeatherPropertiesChanged() {
if (this._weatherProxy.g_name_owner == null)
return;
this._settings.set_boolean('automatic-location',
this._weatherProxy.AutomaticLocation);
this._settings.set_value('locations',
new GLib.Variant('av', this._weatherProxy.Locations));
}
_onInstalledChanged() {
let hadApp = this._weatherApp != null;
this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
let haveApp = this._weatherApp != null;
if (hadApp !== haveApp)
this.emit('changed');
let neededAuth = this._needsAuth;
this._needsAuth = this._weatherApp === null ||
this._weatherApp.app_info.has_key('X-Flatpak');
if (neededAuth !== this._needsAuth)
this._updateAutoLocation();
} }
_loadInfo() { _loadInfo() {
@@ -213,7 +137,7 @@ var WeatherClient = class {
this._weatherInfo.abort(); this._weatherInfo.abort();
this._weatherInfo.set_location(location); this._weatherInfo.set_location(location);
this._locationValid = location != null; this._locationValid = (location != null);
this._weatherInfo.set_enabled_providers(location ? this._providers : 0); this._weatherInfo.set_enabled_providers(location ? this._providers : 0);
@@ -249,8 +173,8 @@ var WeatherClient = class {
(o, res) => { (o, res) => {
try { try {
this._gclueService = Geoclue.Simple.new_finish(res); this._gclueService = Geoclue.Simple.new_finish(res);
} catch (e) { } catch(e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`); log('Failed to connect to Geoclue2 service: ' + e.message);
this._setLocation(this._mostRecentLocation); this._setLocation(this._mostRecentLocation);
return; return;
} }
@@ -269,8 +193,8 @@ var WeatherClient = class {
this._setLocation(location); this._setLocation(location);
} }
_onAutomaticLocationChanged() { _onAutomaticLocationChanged(settings, key) {
let useAutoLocation = this._settings.get_boolean('automatic-location'); let useAutoLocation = settings.get_boolean(key);
if (this._autoLocationRequested == useAutoLocation) if (this._autoLocationRequested == useAutoLocation)
return; return;
@@ -288,9 +212,8 @@ var WeatherClient = class {
this._setLocation(this._mostRecentLocation); this._setLocation(this._mostRecentLocation);
} }
_onLocationsChanged() { _onLocationsChanged(settings, key) {
let locations = this._settings.get_value('locations').deep_unpack(); let serialized = settings.get_value(key).deep_unpack().shift();
let serialized = locations.shift();
let mostRecentLocation = null; let mostRecentLocation = null;
if (serialized) if (serialized)
@@ -306,12 +229,12 @@ var WeatherClient = class {
} }
_onPermStoreChanged(proxy, sender, params) { _onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted_, data_, perms] = params; let [table, id, deleted, data, perms] = params;
if (table != 'gnome' || id != 'geolocation') if (table != 'gnome' || id != 'geolocation')
return; return;
let permission = perms['org.gnome.Weather'] || ['NONE']; let permission = perms['org.gnome.Weather.Application'] || ['NONE'];
let [accuracy] = permission; let [accuracy] = permission;
this._weatherAuthorized = accuracy != 'NONE'; this._weatherAuthorized = accuracy != 'NONE';

View File

@@ -1,9 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported run, script_overviewShowStart, script_overviewShowDone,
script_applicationsShowStart, script_applicationsShowDone,
script_afterShowHide, malloc_usedSize, glx_swapComplete,
clutter_stagePaintDone */
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^malloc", "^glx", "^clutter"] }] */
const System = imports.system; const System = imports.system;
@@ -15,7 +10,7 @@ const Scripting = imports.ui.scripting;
// someone should be able to get an idea of how well the shell is performing // someone should be able to get an idea of how well the shell is performing
// on a particular system. // on a particular system.
var METRICS = { let METRICS = {
overviewLatencyFirst: overviewLatencyFirst:
{ description: "Time to first frame after triggering overview, first time", { description: "Time to first frame after triggering overview, first time",
units: "us" }, units: "us" },
@@ -24,7 +19,7 @@ var METRICS = {
units: "frames / s" }, units: "frames / s" },
overviewLatencySubsequent: overviewLatencySubsequent:
{ description: "Time to first frame after triggering overview, second time", { description: "Time to first frame after triggering overview, second time",
units: "us" }, units: "us"},
overviewFpsSubsequent: overviewFpsSubsequent:
{ description: "Frames rate when going to the overview, second time", { description: "Frames rate when going to the overview, second time",
units: "frames / s" }, units: "frames / s" },
@@ -57,7 +52,7 @@ var METRICS = {
units: "us" }, units: "us" },
applicationsShowTimeSubsequent: applicationsShowTimeSubsequent:
{ description: "Time to switch to applications view, second time", { description: "Time to switch to applications view, second time",
units: "us" }, units: "us"}
}; };
let WINDOW_CONFIGS = [ let WINDOW_CONFIGS = [
@@ -67,10 +62,10 @@ let WINDOW_CONFIGS = [
{ width: 640, height: 480, alpha: false, maximized: true, count: 5, metric: 'overviewFps5Maximized' }, { width: 640, height: 480, alpha: false, maximized: true, count: 5, metric: 'overviewFps5Maximized' },
{ width: 640, height: 480, alpha: false, maximized: true, count: 10, metric: 'overviewFps10Maximized' }, { width: 640, height: 480, alpha: false, maximized: true, count: 10, metric: 'overviewFps10Maximized' },
{ width: 640, height: 480, alpha: true, maximized: false, count: 5, metric: 'overviewFps5Alpha' }, { width: 640, height: 480, alpha: true, maximized: false, count: 5, metric: 'overviewFps5Alpha' },
{ width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }, { width: 640, height: 480, alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha' }
]; ];
function *run() { function run() {
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview"); Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview"); Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
@@ -94,12 +89,11 @@ function *run() {
let config = WINDOW_CONFIGS[i / 2]; let config = WINDOW_CONFIGS[i / 2];
yield Scripting.destroyTestWindows(); yield Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++) { for (let k = 0; k < config.count; k++)
yield Scripting.createTestWindow({ width: config.width, yield Scripting.createTestWindow({ width: config.width,
height: config.height, height: config.height,
alpha: config.alpha, alpha: config.alpha,
maximized: config.maximized }); maximized: config.maximized });
}
yield Scripting.waitTestWindows(); yield Scripting.waitTestWindows();
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
@@ -127,12 +121,10 @@ function *run() {
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates Main.overview._dash.showAppsButton.checked = true;
Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates Main.overview._dash.showAppsButton.checked = false;
Main.overview.dash.showAppsButton.checked = false;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
} }
} }
@@ -144,6 +136,7 @@ let overviewFrames;
let overviewLatency; let overviewLatency;
let mallocUsedSize = 0; let mallocUsedSize = 0;
let overviewShowCount = 0; let overviewShowCount = 0;
let firstOverviewUsedSize;
let haveSwapComplete = false; let haveSwapComplete = false;
let applicationsShowStart; let applicationsShowStart;
let applicationsShowCount = 0; let applicationsShowCount = 0;
@@ -155,7 +148,7 @@ function script_overviewShowStart(time) {
overviewFrames = 0; overviewFrames = 0;
} }
function script_overviewShowDone(_time) { function script_overviewShowDone(time) {
// We've set up the state at the end of the zoom out, but we // We've set up the state at the end of the zoom out, but we
// need to wait for one more frame to paint before we count // need to wait for one more frame to paint before we count
// ourselves as done. // ourselves as done.
@@ -174,11 +167,12 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart; METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
} }
function script_afterShowHide(_time) { function script_afterShowHide(time) {
if (overviewShowCount == 1) if (overviewShowCount == 1) {
METRICS.usedAfterOverview.value = mallocUsedSize; METRICS.usedAfterOverview.value = mallocUsedSize;
else } else {
METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value; METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value;
}
} }
function malloc_usedSize(time, bytes) { function malloc_usedSize(time, bytes) {

View File

@@ -1,17 +1,12 @@
/* exported run, script_desktopShown, script_overviewShowStart, const Clutter = imports.gi.Clutter;
script_overviewShowDone, script_applicationsShowStart, const Gio = imports.gi.Gio;
script_applicationsShowDone, script_mainViewDrawStart, const Gtk = imports.gi.Gtk;
script_mainViewDrawDone, script_overviewDrawStart, const Meta = imports.gi.Meta;
script_overviewDrawDone, script_redrawTestStart,
script_redrawTestDone, script_collectTimings,
script_geditLaunch, script_geditFirstFrame,
clutter_stagePaintStart, clutter_paintCompletedTimestamp */
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^clutter"] }] */
const { Clutter, Gio, Shell } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const Scripting = imports.ui.scripting; const Scripting = imports.ui.scripting;
const Shell = imports.gi.Shell;
var METRICS = { let METRICS = {
timeToDesktop: timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing", { description: "Time from starting graphical.target to desktop showing",
units: "us" }, units: "us" },
@@ -39,7 +34,7 @@ var METRICS = {
geditStartTime: geditStartTime:
{ description: "Time from gedit launch to window drawn", { description: "Time from gedit launch to window drawn",
units: "us" }, units: "us" },
}; }
function waitAndDraw(milliseconds) { function waitAndDraw(milliseconds) {
let cb; let cb;
@@ -47,7 +42,7 @@ function waitAndDraw(milliseconds) {
let timeline = new Clutter.Timeline({ duration: milliseconds }); let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start(); timeline.start();
timeline.connect('new-frame', (_timeline, _frame) => { timeline.connect('new-frame', (timeline, frame) => {
global.stage.queue_redraw(); global.stage.queue_redraw();
}); });
@@ -57,7 +52,7 @@ function waitAndDraw(milliseconds) {
cb(); cb();
}); });
return callback => (cb = callback); return callback => { cb = callback; };
} }
function waitSignal(object, signal) { function waitSignal(object, signal) {
@@ -69,7 +64,7 @@ function waitSignal(object, signal) {
cb(); cb();
}); });
return callback => (cb = callback); return callback => { cb = callback; };
} }
function extractBootTimestamp() { function extractBootTimestamp() {
@@ -82,8 +77,8 @@ function extractBootTimestamp() {
let result = null; let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe()); let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) { // eslint-disable-line no-constant-condition while (true) {
let [line, length_] = datastream.read_line_utf8(null); let [line, length] = datastream.read_line_utf8(null);
if (line === null) if (line === null)
break; break;
@@ -94,7 +89,7 @@ function extractBootTimestamp() {
return result; return result;
} }
function *run() { function run() {
Scripting.defineScriptEvent("desktopShown", "Finished initial animation"); Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview"); Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
@@ -113,10 +108,7 @@ function *run() {
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown'); Scripting.scriptEvent('desktopShown');
let interfaceSettings = new Gio.Settings({ Gtk.Settings.get_default().gtk_enable_animations = false;
schema_id: 'org.gnome.desktop.interface',
});
interfaceSettings.set_boolean('enable-animations', false);
Scripting.scriptEvent('overviewShowStart'); Scripting.scriptEvent('overviewShowStart');
Main.overview.show(); Main.overview.show();
@@ -126,8 +118,7 @@ function *run() {
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates Main.overview._dash.showAppsButton.checked = true;
Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');
@@ -137,9 +128,9 @@ function *run() {
Main.overview.hide(); Main.overview.hide();
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
// --------------------- // ////////////////////////////////////////
// Tests of redraw speed // // Tests of redraw speed
// --------------------- // ////////////////////////////////////////
global.frame_timestamps = true; global.frame_timestamps = true;
global.frame_finish_timestamp = true; global.frame_finish_timestamp = true;
@@ -167,7 +158,7 @@ function *run() {
Main.overview.hide(); Main.overview.hide();
yield Scripting.createTestWindow({ maximized: true, yield Scripting.createTestWindow({ maximized: true,
redraws: true }); redraws: true});
yield Scripting.waitTestWindows(); yield Scripting.waitTestWindows();
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
@@ -186,6 +177,8 @@ function *run() {
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default(); let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop'); let app = appSys.lookup_app('org.gnome.gedit.desktop');
@@ -211,7 +204,7 @@ function *run() {
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
interfaceSettings.set_boolean('enable-animations', true); Gtk.Settings.get_default().gtk_enable_animations = true;
} }
let overviewShowStart; let overviewShowStart;
@@ -242,31 +235,31 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart; METRICS.applicationsShowTime.value = time - applicationsShowStart;
} }
function script_mainViewDrawStart(_time) { function script_mainViewDrawStart(time) {
redrawTiming = 'mainView'; redrawTiming = 'mainView';
} }
function script_mainViewDrawDone(_time) { function script_mainViewDrawDone(time) {
redrawTiming = null; redrawTiming = null;
} }
function script_overviewDrawStart(_time) { function script_overviewDrawStart(time) {
redrawTiming = 'overview'; redrawTiming = 'overview';
} }
function script_overviewDrawDone(_time) { function script_overviewDrawDone(time) {
redrawTiming = null; redrawTiming = null;
} }
function script_redrawTestStart(_time) { function script_redrawTestStart(time) {
redrawTiming = 'application'; redrawTiming = 'application';
} }
function script_redrawTestDone(_time) { function script_redrawTestDone(time) {
redrawTiming = null; redrawTiming = null;
} }
function script_collectTimings(_time) { function script_collectTimings(time) {
for (let timing in redrawTimes) { for (let timing in redrawTimes) {
let times = redrawTimes[timing]; let times = redrawTimes[timing];
times.sort((a, b) => a - b); times.sort((a, b) => a - b);
@@ -277,11 +270,11 @@ function script_collectTimings(_time) {
if (len == 0) if (len == 0)
median = -1; median = -1;
else if (len % 2 == 1) else if (len % 2 == 1)
median = times[(len - 1) / 2]; median = times[(len - 1)/ 2];
else else
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2); median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
METRICS[`${timing}RedrawTime`].value = median; METRICS[timing + 'RedrawTime'].value = median;
} }
} }

View File

@@ -1,7 +1,12 @@
/* exported main */
const Format = imports.format; const Format = imports.format;
const Gettext = imports.gettext; const Gettext = imports.gettext;
const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi; const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Soup = imports.gi.Soup;
const WebKit = imports.gi.WebKit2;
const _ = Gettext.gettext; const _ = Gettext.gettext;
@@ -11,17 +16,18 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
const PortalHelperResult = { const PortalHelperResult = {
CANCELLED: 0, CANCELLED: 0,
COMPLETED: 1, COMPLETED: 1,
RECHECK: 2, RECHECK: 2
}; };
const PortalHelperSecurityLevel = { const PortalHelperSecurityLevel = {
NOT_YET_DETERMINED: 0, NOT_YET_DETERMINED: 0,
SECURE: 1, SECURE: 1,
INSECURE: 2, INSECURE: 2
}; };
const INACTIVITY_TIMEOUT = 30000; //ms
const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org'; const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
const CONNECTIVITY_CHECK_URI = `http://${CONNECTIVITY_CHECK_HOST}`; const CONNECTIVITY_CHECK_URI = 'http://' + CONNECTIVITY_CHECK_HOST;
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC; const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper'); const HelperDBusInterface = loadInterfaceXML('org.gnome.Shell.PortalHelper');
@@ -59,7 +65,7 @@ class PortalHeaderBar extends Gtk.HeaderBar {
single_line_mode: true, single_line_mode: true,
ellipsize: Pango.EllipsizeMode.END, ellipsize: Pango.EllipsizeMode.END,
valign: Gtk.Align.BASELINE, valign: Gtk.Align.BASELINE,
selectable: true }); selectable: true});
this.subtitleLabel.get_style_context().add_class('subtitle'); this.subtitleLabel.get_style_context().add_class('subtitle');
hbox.add(this.subtitleLabel); hbox.add(this.subtitleLabel);
@@ -92,7 +98,7 @@ class PortalHeaderBar extends Gtk.HeaderBar {
var PortalWindow = GObject.registerClass( var PortalWindow = GObject.registerClass(
class PortalWindow extends Gtk.ApplicationWindow { class PortalWindow extends Gtk.ApplicationWindow {
_init(application, url, timestamp, doneCallback) { _init(application, url, timestamp, doneCallback) {
super._init({ application }); super._init({ application: application });
this.connect('delete-event', this.destroyWindow.bind(this)); this.connect('delete-event', this.destroyWindow.bind(this));
this._headerBar = new PortalHeaderBar(); this._headerBar = new PortalHeaderBar();
@@ -152,7 +158,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._webView.load_uri(this._originalUrl); this._webView.load_uri(this._originalUrl);
} }
vfunc_delete_event(_event) { vfunc_delete_event(event) {
if (this._recheckAtExit) if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK); this._doneCallback(PortalHelperResult.RECHECK);
else else
@@ -178,7 +184,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
} }
_onLoadFailedWithTlsErrors(view, failingURI, certificate, _errors) { _onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
let uri = new Soup.URI(failingURI); let uri = new Soup.URI(failingURI);
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host()); this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
@@ -265,7 +271,7 @@ class WebPortalHelper extends Gtk.Application {
this._queue = []; this._queue = [];
let action = new Gio.SimpleAction({ name: 'quit' }); let action = new Gio.SimpleAction({ name: 'quit' });
action.connect('activate', () => this.active_window.destroyWindow()); action.connect('activate', () => { this.active_window.destroyWindow(); });
this.add_action(action); this.add_action(action);
} }
@@ -287,7 +293,7 @@ class WebPortalHelper extends Gtk.Application {
} }
Authenticate(connection, url, timestamp) { Authenticate(connection, url, timestamp) {
this._queue.push({ connection, url, timestamp }); this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue(); this._processQueue();
} }

View File

@@ -1,5 +1,9 @@
/* exported AccessDialogDBus */ const Clutter = imports.gi.Clutter;
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const CheckBox = imports.ui.checkBox; const CheckBox = imports.ui.checkBox;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
@@ -13,13 +17,12 @@ const AccessIface = loadInterfaceXML('org.freedesktop.impl.portal.Access');
var DialogResponse = { var DialogResponse = {
OK: 0, OK: 0,
CANCEL: 1, CANCEL: 1,
CLOSED: 2, CLOSED: 2
}; };
var AccessDialog = GObject.registerClass( var AccessDialog = class extends ModalDialog.ModalDialog {
class AccessDialog extends ModalDialog.ModalDialog { constructor(invocation, handle, title, subtitle, body, options) {
_init(invocation, handle, title, subtitle, body, options) { super({ styleClass: 'access-dialog' });
super._init({ styleClass: 'access-dialog' });
this._invocation = invocation; this._invocation = invocation;
this._handle = handle; this._handle = handle;
@@ -35,7 +38,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
_buildLayout(title, subtitle, body, options) { _buildLayout(title, subtitle, body, options) {
// No support for non-modal system dialogs, so ignore the option // No support for non-modal system dialogs, so ignore the option
// let modal = options['modal'] || true; //let modal = options['modal'] || true;
let denyLabel = options['deny_label'] || _("Deny Access"); let denyLabel = options['deny_label'] || _("Deny Access");
let grantLabel = options['grant_label'] || _("Grant Access"); let grantLabel = options['grant_label'] || _("Grant Access");
let iconName = options['icon'] || null; let iconName = options['icon'] || null;
@@ -56,8 +59,8 @@ class AccessDialog extends ModalDialog.ModalDialog {
let check = new CheckBox.CheckBox(); let check = new CheckBox.CheckBox();
check.getLabelActor().text = name; check.getLabelActor().text = name;
check.checked = selected == "true"; check.actor.checked = selected == "true";
content.insertBeforeBody(check); content.insertBeforeBody(check.actor);
this._choices.set(id, check); this._choices.set(id, check);
} }
@@ -70,7 +73,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this.addButton({ label: grantLabel, this.addButton({ label: grantLabel,
action: () => { action: () => {
this._sendResponse(DialogResponse.OK); this._sendResponse(DialogResponse.OK);
} }); }});
} }
open() { open() {
@@ -80,7 +83,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this._requestExported = this._request.export(connection, this._handle); this._requestExported = this._request.export(connection, this._handle);
} }
CloseAsync(invocation, _params) { CloseAsync(invocation, params) {
if (this._invocation.get_sender() != invocation.get_sender()) { if (this._invocation.get_sender() != invocation.get_sender()) {
invocation.return_error_literal(Gio.DBusError, invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED, Gio.DBusError.ACCESS_DENIED,
@@ -99,7 +102,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
let results = {}; let results = {};
if (response == DialogResponse.OK) { if (response == DialogResponse.OK) {
for (let [id, check] of this._choices) { for (let [id, check] of this._choices) {
let checked = check.checked ? 'true' : 'false'; let checked = check.actor.checked ? 'true' : 'false';
results[id] = new GLib.Variant('s', checked); results[id] = new GLib.Variant('s', checked);
} }
} }
@@ -111,7 +114,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
}); });
this.close(); this.close();
} }
}); };
var AccessDialogDBus = class { var AccessDialogDBus = class {
constructor() { constructor() {
@@ -133,10 +136,10 @@ var AccessDialogDBus = class {
return; return;
} }
let [handle, appId, parentWindow_, title, subtitle, body, options] = params; let [handle, appId, parentWindow, title, subtitle, body, options] = params;
// We probably want to use parentWindow and global.display.focus_window // We probably want to use parentWindow and global.display.focus_window
// for this check in the future // for this check in the future
if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) { if (appId && appId + '.desktop' != this._windowTracker.focus_app.id) {
invocation.return_error_literal(Gio.DBusError, invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED, Gio.DBusError.ACCESS_DENIED,
'Only the focused app is allowed to show a system access dialog'); 'Only the focused app is allowed to show a system access dialog');
@@ -147,7 +150,7 @@ var AccessDialogDBus = class {
subtitle, body, options); subtitle, body, options);
dialog.open(); dialog.open();
dialog.connect('closed', () => (this._accessDialog = null)); dialog.connect('closed', () => { this._accessDialog = null; });
this._accessDialog = dialog; this._accessDialog = dialog;
} }

View File

@@ -1,17 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AppSwitcherPopup, GroupCyclerPopup, WindowSwitcherPopup,
WindowCyclerPopup */
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const Main = imports.ui.main; const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup; const SwitcherPopup = imports.ui.switcherPopup;
const Tweener = imports.ui.tweener;
var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds var APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
var THUMBNAIL_DEFAULT_SIZE = 256; var THUMBNAIL_DEFAULT_SIZE = 256;
var THUMBNAIL_POPUP_TIME = 500; // milliseconds var THUMBNAIL_POPUP_TIME = 500; // milliseconds
var THUMBNAIL_FADE_TIME = 100; // milliseconds var THUMBNAIL_FADE_TIME = 0.1; // seconds
var WINDOW_PREVIEW_SIZE = 128; var WINDOW_PREVIEW_SIZE = 128;
var APP_ICON_SIZE = 96; var APP_ICON_SIZE = 96;
@@ -36,7 +43,7 @@ function _createWindowClone(window, size) {
// usual hack for the usual bug in ClutterBinLayout... // usual hack for the usual bug in ClutterBinLayout...
x_expand: true, x_expand: true,
y_expand: true }); y_expand: true });
} };
function getWindows(workspace) { function getWindows(workspace) {
// We ignore skip-taskbar windows in switchers, but if they are attached // We ignore skip-taskbar windows in switchers, but if they are attached
@@ -62,7 +69,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this.thumbnailsVisible = false; this.thumbnailsVisible = false;
let apps = Shell.AppSystem.get_default().get_running(); let apps = Shell.AppSystem.get_default().get_running ();
if (apps.length == 0) if (apps.length == 0)
return; return;
@@ -87,9 +94,9 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
let hPadding = leftPadding + rightPadding; let hPadding = leftPadding + rightPadding;
let icon = this._items[this._selectedIndex]; let icon = this._items[this._selectedIndex];
let [posX] = icon.get_transformed_position(); let [posX, posY] = icon.get_transformed_position();
let thumbnailCenter = posX + icon.width / 2; let thumbnailCenter = posX + icon.width / 2;
let [, childNaturalWidth] = this._thumbnails.get_preferred_width(-1); let [childMinWidth, childNaturalWidth] = this._thumbnails.get_preferred_width(-1);
childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2)); childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2));
if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) { if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) {
let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding; let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding;
@@ -103,7 +110,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
childBox.x2 = primary.x + primary.width - rightPadding; childBox.x2 = primary.x + primary.width - rightPadding;
childBox.y1 = this._switcherList.allocation.y2 + spacing; childBox.y1 = this._switcherList.allocation.y2 + spacing;
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1); this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1); let [childMinHeight, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
childBox.y2 = childBox.y1 + childNaturalHeight; childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags); this._thumbnails.allocate(childBox, flags);
} }
@@ -111,12 +118,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_initialSelection(backward, binding) { _initialSelection(backward, binding) {
if (binding == 'switch-group') { if (binding == 'switch-group') {
if (backward) if (backward) {
this._select(0, this._items[0].cachedWindows.length - 1); this._select(0, this._items[0].cachedWindows.length - 1);
else if (this._items[0].cachedWindows.length > 1) } else {
if (this._items[0].cachedWindows.length > 1)
this._select(0, 1); this._select(0, 1);
else else
this._select(0, 0); this._select(0, 0);
}
} else if (binding == 'switch-group-backward') { } else if (binding == 'switch-group-backward') {
this._select(0, this._items[0].cachedWindows.length - 1); this._select(0, this._items[0].cachedWindows.length - 1);
} else if (binding == 'switch-applications-backward') { } else if (binding == 'switch-applications-backward') {
@@ -178,26 +187,27 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._select(this._next()); this._select(this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) { } else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) {
this._select(this._previous()); this._select(this._previous());
} else if (keysym === Clutter.KEY_q) { } else if (keysym == Clutter.q) {
this._quitApplication(this._selectedIndex); this._quitApplication(this._selectedIndex);
} else if (this._thumbnailsFocused) { } else if (this._thumbnailsFocused) {
if (keysym === Clutter.KEY_Left) if (keysym == Clutter.Left)
this._select(this._selectedIndex, this._previousWindow()); this._select(this._selectedIndex, this._previousWindow());
else if (keysym === Clutter.KEY_Right) else if (keysym == Clutter.Right)
this._select(this._selectedIndex, this._nextWindow()); this._select(this._selectedIndex, this._nextWindow());
else if (keysym === Clutter.KEY_Up) else if (keysym == Clutter.Up)
this._select(this._selectedIndex, null, true); this._select(this._selectedIndex, null, true);
else if (keysym === Clutter.KEY_w || keysym === Clutter.KEY_F4) else if (keysym == Clutter.w || keysym == Clutter.F4)
this._closeAppWindow(this._selectedIndex, this._currentWindow); this._closeAppWindow(this._selectedIndex, this._currentWindow);
else else
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} else if (keysym == Clutter.KEY_Left) {
this._select(this._previous());
} else if (keysym == Clutter.KEY_Right) {
this._select(this._next());
} else if (keysym == Clutter.KEY_Down) {
this._select(this._selectedIndex, 0);
} else { } else {
if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)
this._select(this._next());
else if (keysym == Clutter.Down)
this._select(this._selectedIndex, 0);
else
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
@@ -288,14 +298,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
if (this._thumbnails) if (this._thumbnails)
this._destroyThumbnails(); this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0) if (this._thumbnailTimeoutId != 0)
GLib.source_remove(this._thumbnailTimeoutId); Mainloop.source_remove(this._thumbnailTimeoutId);
} }
/** /**
* _select: * _select:
* @param {number} app: index of the app to select * @app: index of the app to select
* @param {number=} window: index of which of @app's windows to select * @window: (optional) index of which of @app's windows to select
* @param {bool} forceAppFocus: optional flag, see below * @forceAppFocus: optional flag, see below
* *
* Selects the indicated @app, and optional @window, and sets * Selects the indicated @app, and optional @window, and sets
* this._thumbnailsFocused appropriately to indicate whether the * this._thumbnailsFocused appropriately to indicate whether the
@@ -323,7 +333,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
if (this._thumbnailTimeoutId != 0) { if (this._thumbnailTimeoutId != 0) {
GLib.source_remove(this._thumbnailTimeoutId); Mainloop.source_remove(this._thumbnailTimeoutId);
this._thumbnailTimeoutId = 0; this._thumbnailTimeoutId = 0;
} }
@@ -340,8 +350,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.highlight(window, forceAppFocus); this._thumbnails.highlight(window, forceAppFocus);
} else if (this._items[this._selectedIndex].cachedWindows.length > 1 && } else if (this._items[this._selectedIndex].cachedWindows.length > 1 &&
!forceAppFocus) { !forceAppFocus) {
this._thumbnailTimeoutId = GLib.timeout_add( this._thumbnailTimeoutId = Mainloop.timeout_add (
GLib.PRIORITY_DEFAULT,
THUMBNAIL_POPUP_TIME, THUMBNAIL_POPUP_TIME,
this._timeoutPopupThumbnails.bind(this)); this._timeoutPopupThumbnails.bind(this));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails'); GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
@@ -358,22 +367,22 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
_destroyThumbnails() { _destroyThumbnails() {
let thumbnailsActor = this._thumbnails; let thumbnailsActor = this._thumbnails;
this._thumbnails.ease({ Tweener.addTween(thumbnailsActor,
opacity: 0, { opacity: 0,
duration: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: () => {
thumbnailsActor.destroy(); thumbnailsActor.destroy();
this.thumbnailsVisible = false; this.thumbnailsVisible = false;
}, }
}); });
this._thumbnails = null; this._thumbnails = null;
if (this._switcherList._items[this._selectedIndex]) if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state(Atk.StateType.EXPANDED); this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
} }
_createThumbnails() { _createThumbnails() {
this._thumbnails = new ThumbnailList(this._items[this._selectedIndex].cachedWindows); this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
this._thumbnails.connect('item-activated', this._windowActivated.bind(this)); this._thumbnails.connect('item-activated', this._windowActivated.bind(this));
this._thumbnails.connect('item-entered', this._windowEntered.bind(this)); this._thumbnails.connect('item-entered', this._windowEntered.bind(this));
this._thumbnails.connect('item-removed', this._windowRemoved.bind(this)); this._thumbnails.connect('item-removed', this._windowRemoved.bind(this));
@@ -389,39 +398,38 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.get_allocation_box(); this._thumbnails.get_allocation_box();
this._thumbnails.opacity = 0; this._thumbnails.opacity = 0;
this._thumbnails.ease({ Tweener.addTween(this._thumbnails,
opacity: 255, { opacity: 255,
duration: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => { onComplete: () => { this.thumbnailsVisible = true; }
this.thumbnailsVisible = true;
},
}); });
this._switcherList._items[this._selectedIndex].add_accessible_state(Atk.StateType.EXPANDED); this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
} }
}); });
var CyclerHighlight = GObject.registerClass( class CyclerHighlight {
class CyclerHighlight extends St.Widget { constructor() {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
this._window = null; this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._clone = new Clutter.Clone(); this._clone = new Clutter.Clone();
this.add_actor(this._clone); this.actor.add_actor(this._clone);
this._highlight = new St.Widget({ style_class: 'cycler-highlight' }); this._highlight = new St.Widget({ style_class: 'cycler-highlight' });
this.add_actor(this._highlight); this.actor.add_actor(this._highlight);
let coordinate = Clutter.BindCoordinate.ALL; let coordinate = Clutter.BindCoordinate.ALL;
let constraint = new Clutter.BindConstraint({ coordinate }); let constraint = new Clutter.BindConstraint({ coordinate: coordinate });
this._clone.bind_property('source', constraint, 'source', 0); this._clone.bind_property('source', constraint, 'source', 0);
this.add_constraint(constraint); this.actor.add_constraint(constraint);
this.connect('notify::allocation', this._onAllocationChanged.bind(this)); this.actor.connect('notify::allocation',
this.connect('destroy', this._onDestroy.bind(this)); this._onAllocationChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
} }
set window(w) { set window(w) {
@@ -433,8 +441,8 @@ class CyclerHighlight extends St.Widget {
if (this._clone.source) if (this._clone.source)
this._clone.source.sync_visibility(); this._clone.source.sync_visibility();
let windowActor = this._window let windowActor = this._window ? this._window.get_compositor_private()
? this._window.get_compositor_private() : null; : null;
if (windowActor) if (windowActor)
windowActor.hide(); windowActor.hide();
@@ -447,7 +455,7 @@ class CyclerHighlight extends St.Widget {
this._highlight.set_size(0, 0); this._highlight.set_size(0, 0);
this._highlight.hide(); this._highlight.hide();
} else { } else {
let [x, y] = this.allocation.get_origin(); let [x, y] = this.actor.allocation.get_origin();
let rect = this._window.get_frame_rect(); let rect = this._window.get_frame_rect();
this._highlight.set_size(rect.width, rect.height); this._highlight.set_size(rect.width, rect.height);
this._highlight.set_position(rect.x - x, rect.y - y); this._highlight.set_position(rect.x - x, rect.y - y);
@@ -458,7 +466,7 @@ class CyclerHighlight extends St.Widget {
_onDestroy() { _onDestroy() {
this.window = null; this.window = null;
} }
}); };
// We don't show an actual popup, so just provide what SwitcherPopup // We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList // expects instead of inheriting from SwitcherList
@@ -468,15 +476,17 @@ var CyclerList = GObject.registerClass({
'item-removed': { param_types: [GObject.TYPE_INT] }, 'item-removed': { param_types: [GObject.TYPE_INT] },
'item-highlighted': { param_types: [GObject.TYPE_INT] } }, 'item-highlighted': { param_types: [GObject.TYPE_INT] } },
}, class CyclerList extends St.Widget { }, class CyclerList extends St.Widget {
highlight(index, _justOutline) { highlight(index, justOutline) {
this.emit('item-highlighted', index); this.emit('item-highlighted', index);
} }
}); });
var CyclerPopup = GObject.registerClass({ var CyclerPopup = GObject.registerClass(
GTypeFlags: GObject.TypeFlags.ABSTRACT, class CyclerPopup extends SwitcherPopup.SwitcherPopup {
}, class CyclerPopup extends SwitcherPopup.SwitcherPopup {
_init() { _init() {
if (new.target === CyclerPopup)
throw new TypeError('Cannot instantiate abstract class ' + new.target.name);
super._init(); super._init();
this._items = this._getWindows(); this._items = this._getWindows();
@@ -485,7 +495,7 @@ var CyclerPopup = GObject.registerClass({
return; return;
this._highlight = new CyclerHighlight(); this._highlight = new CyclerHighlight();
global.window_group.add_actor(this._highlight); global.window_group.add_actor(this._highlight.actor);
this._switcherList = new CyclerList(); this._switcherList = new CyclerList();
this._switcherList.connect('item-highlighted', (list, index) => { this._switcherList.connect('item-highlighted', (list, index) => {
@@ -493,9 +503,9 @@ var CyclerPopup = GObject.registerClass({
}); });
} }
_highlightItem(index, _justOutline) { _highlightItem(index, justOutline) {
this._highlight.window = this._items[index]; this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight, null); global.window_group.set_child_above_sibling(this._highlight.actor, null);
} }
_finish() { _finish() {
@@ -525,7 +535,7 @@ var CyclerPopup = GObject.registerClass({
} }
_onDestroy() { _onDestroy() {
this._highlight.destroy(); this._highlight.actor.destroy();
super._onDestroy(); super._onDestroy();
} }
@@ -588,18 +598,20 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
_keyPressHandler(keysym, action) { _keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(this._next()); this._select(this._next());
else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) } else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
this._select(this._previous()); this._select(this._previous());
else if (keysym == Clutter.KEY_Left) } else {
if (keysym == Clutter.Left)
this._select(this._previous()); this._select(this._previous());
else if (keysym == Clutter.KEY_Right) else if (keysym == Clutter.Right)
this._select(this._next()); this._select(this._next());
else if (keysym == Clutter.KEY_w || keysym == Clutter.KEY_F4) else if (keysym == Clutter.w || keysym == Clutter.F4)
this._closeWindow(this._selectedIndex); this._closeWindow(this._selectedIndex);
else else
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@@ -614,8 +626,9 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
var WindowCyclerPopup = GObject.registerClass( var WindowCyclerPopup = GObject.registerClass(
class WindowCyclerPopup extends CyclerPopup { class WindowCyclerPopup extends CyclerPopup {
_init() { _init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
super._init(); super._init();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
} }
_getWindows() { _getWindows() {
@@ -650,20 +663,24 @@ class AppIcon extends St.BoxLayout {
this.app = app; this.app = app;
this.icon = null; this.icon = null;
this._iconBin = new St.Bin(); this._iconBin = new St.Bin({ x_fill: true, y_fill: true });
this.add_child(this._iconBin); this.add(this._iconBin, { x_fill: false, y_fill: false } );
this.label = new St.Label({ this.label = new St.Label({ text: this.app.get_name() });
text: this.app.get_name(), this.add(this.label, { x_fill: false });
x_align: Clutter.ActorAlign.CENTER,
});
this.add_child(this.label);
} }
// eslint-disable-next-line camelcase
set_size(size) { set_size(size) {
this.icon = this.app.create_icon_texture(size); this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon; this._iconBin.child = this.icon;
this._iconBin.set_size(size, size);
}
vfunc_get_preferred_width(forHeight) {
let [minWidth, ] = super.vfunc_get_preferred_width(forHeight);
minWidth = Math.max(minWidth, forHeight);
return [minWidth, minWidth];
} }
}); });
@@ -693,7 +710,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// Cache the window list now; we don't handle dynamic changes here, // Cache the window list now; we don't handle dynamic changes here,
// and we don't want to be continually retrieving it // and we don't want to be continually retrieving it
appIcon.cachedWindows = allWindows.filter( appIcon.cachedWindows = allWindows.filter(
w => windowTracker.get_window_app(w) == appIcon.app w => windowTracker.get_window_app (w) == appIcon.app
); );
if (appIcon.cachedWindows.length > 0) if (appIcon.cachedWindows.length > 0)
this._addIcon(appIcon); this._addIcon(appIcon);
@@ -708,7 +725,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_onDestroy() { _onDestroy() {
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
GLib.source_remove(this._mouseTimeOutId); Mainloop.source_remove(this._mouseTimeOutId);
this.icons.forEach(icon => { this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId); icon.app.disconnect(icon._stateChangedId);
@@ -717,16 +734,15 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_setIconSize() { _setIconSize() {
let j = 0; let j = 0;
while (this._items.length > 1 && this._items[j].style_class != 'item-box') while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++; j++;
}
let themeNode = this._items[j].get_theme_node(); let themeNode = this._items[j].get_theme_node();
this._list.ensure_style();
let iconPadding = themeNode.get_horizontal_padding(); let iconPadding = themeNode.get_horizontal_padding();
let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT); let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT);
let [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1); let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
let iconSpacing = labelNaturalHeight + iconPadding + iconBorder; let iconSpacing = iconNaturalHeight + iconPadding + iconBorder;
let totalSpacing = this._list.spacing * (this._items.length - 1); let totalSpacing = this._list.spacing * (this._items.length - 1);
// We just assume the whole screen here due to weirdness happing with the passed width // We just assume the whole screen here due to weirdness happing with the passed width
@@ -739,7 +755,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
let iconSize = baseIconSizes[0]; let iconSize = baseIconSizes[0];
if (this._items.length > 1) { if (this._items.length > 1) {
for (let i = 0; i < baseIconSizes.length; i++) { for(let i = 0; i < baseIconSizes.length; i++) {
iconSize = baseIconSizes[i]; iconSize = baseIconSizes[i];
let height = iconSizes[i] + iconSpacing; let height = iconSizes[i] + iconSpacing;
let w = height * this._items.length + totalSpacing; let w = height * this._items.length + totalSpacing;
@@ -750,7 +766,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._iconSize = iconSize; this._iconSize = iconSize;
for (let i = 0; i < this.icons.length; i++) { for(let i = 0; i < this.icons.length; i++) {
if (this.icons[i].icon != null) if (this.icons[i].icon != null)
break; break;
this.icons[i].set_size(iconSize); this.icons[i].set_size(iconSize);
@@ -787,24 +803,21 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// activation when the thumbnail list is open // activation when the thumbnail list is open
_onItemEnter(index) { _onItemEnter(index) {
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
GLib.source_remove(this._mouseTimeOutId); Mainloop.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) { if (this._altTabPopup.thumbnailsVisible) {
this._mouseTimeOutId = GLib.timeout_add( this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
GLib.PRIORITY_DEFAULT,
APP_ICON_HOVER_TIMEOUT,
() => { () => {
this._enterItem(index); this._enterItem(index);
this._mouseTimeOutId = 0; this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem'); GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else { } else
this._itemEntered(index); this._itemEntered(index);
} }
}
_enterItem(index) { _enterItem(index) {
let [x, y] = global.get_pointer(); let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y); let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor)) if (this._items[index].contains(pickedActor))
this._itemEntered(index); this._itemEntered(index);
@@ -845,15 +858,16 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._removeIcon(app); this._removeIcon(app);
}); });
let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' }); let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', () => SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM)); arrow.connect('repaint', () => { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
this.add_actor(arrow); this.add_actor(arrow);
this._arrows.push(arrow); this._arrows.push(arrow);
if (appIcon.cachedWindows.length == 1) if (appIcon.cachedWindows.length == 1)
arrow.hide(); arrow.hide();
else else
item.add_accessible_state(Atk.StateType.EXPANDABLE); item.add_accessible_state (Atk.StateType.EXPANDABLE);
} }
_removeIcon(app) { _removeIcon(app) {
@@ -873,9 +887,9 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
_init(windows) { _init(windows) {
super._init(false); super._init(false);
this._labels = []; this._labels = new Array();
this._thumbnailBins = []; this._thumbnailBins = new Array();
this._clones = []; this._clones = new Array();
this._windows = windows; this._windows = windows;
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
@@ -889,13 +903,12 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
let title = windows[i].get_title(); let title = windows[i].get_title();
if (title) { if (title) {
let name = new St.Label({ let name = new St.Label({ text: title });
text: title, // St.Label doesn't support text-align so use a Bin
// St.Label doesn't support text-align let bin = new St.Bin({ x_align: St.Align.MIDDLE });
x_align: Clutter.ActorAlign.CENTER, this._labels.push(bin);
}); bin.add_actor(name);
this._labels.push(name); box.add_actor(bin);
box.add_actor(name);
this.addItem(box, name); this.addItem(box, name);
} else { } else {
@@ -912,7 +925,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
return; return;
let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding(); let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding();
totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding(); totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding();
let [, labelNaturalHeight] = this._labels[0].get_preferred_height(-1); let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1);
let spacing = this._items[0].child.get_theme_node().get_length('spacing'); let spacing = this._items[0].child.get_theme_node().get_length('spacing');
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor; let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor;
@@ -937,7 +950,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
} }
// Make sure we only do this once // Make sure we only do this once
this._thumbnailBins = []; this._thumbnailBins = new Array();
} }
_removeThumbnail(source, clone) { _removeThumbnail(source, clone) {
@@ -974,7 +987,7 @@ class WindowIcon extends St.BoxLayout {
this._icon = new St.Widget({ layout_manager: new Clutter.BinLayout() }); this._icon = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.add_child(this._icon); this.add(this._icon, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: window.get_title() }); this.label = new St.Label({ text: window.get_title() });
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
@@ -997,10 +1010,9 @@ class WindowIcon extends St.BoxLayout {
size = WINDOW_PREVIEW_SIZE; size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor)); this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
if (this.app) { if (this.app)
this._icon.add_actor(this._createAppIcon(this.app, this._icon.add_actor(this._createAppIcon(this.app,
APP_ICON_SIZE_SMALL)); APP_ICON_SIZE_SMALL));
}
break; break;
case AppIconMode.APP_ICON_ONLY: case AppIconMode.APP_ICON_ONLY:
@@ -1012,9 +1024,9 @@ class WindowIcon extends St.BoxLayout {
} }
_createAppIcon(app, size) { _createAppIcon(app, size) {
let appIcon = app let appIcon = app ? app.create_icon_texture(size)
? app.create_icon_texture(size) : new St.Icon({ icon_name: 'icon-missing',
: new St.Icon({ icon_name: 'icon-missing', icon_size: size }); icon_size: size });
appIcon.x_expand = appIcon.y_expand = true; appIcon.x_expand = appIcon.y_expand = true;
appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END; appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END;
@@ -1041,8 +1053,8 @@ class WindowList extends SwitcherPopup.SwitcherList {
this.addItem(icon, icon.label); this.addItem(icon, icon.label);
this.icons.push(icon); this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', window => { icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
this._removeWindow(window); this._removeWindow(window)
}); });
} }
@@ -1078,7 +1090,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
childBox.y1 = childBox.y2 - this._label.height; childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags); this._label.allocate(childBox, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM); let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM)
childBox.x1 = box.x1; childBox.x1 = box.x1;
childBox.x2 = box.x2; childBox.x2 = box.x2;
childBox.y1 = box.y1; childBox.y1 = box.y1;

View File

@@ -1,26 +1,22 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */
const { Clutter, GLib, GObject, Gio, St } = imports.gi; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const Params = imports.misc.params; const Tweener = imports.ui.tweener;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16; var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300; var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1000; var SPINNER_ANIMATION_DELAY = 1.0;
var Animation = GObject.registerClass(
class Animation extends St.Bin {
_init(file, width, height, speed) {
super._init({ width, height });
this.connect('destroy', this._onDestroy.bind(this));
this.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));
var Animation = class {
constructor(file, width, height, speed) {
this.actor = new St.Bin();
this.actor.connect('destroy', this._onDestroy.bind(this));
this._speed = speed; this._speed = speed;
this._isLoaded = false; this._isLoaded = false;
@@ -28,7 +24,10 @@ class Animation extends St.Bin {
this._timeoutId = 0; this._timeoutId = 0;
this._frame = 0; this._frame = 0;
this._loadFile(file, width, height); 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);
} }
play() { play() {
@@ -45,50 +44,19 @@ class Animation extends St.Bin {
stop() { stop() {
if (this._timeoutId > 0) { if (this._timeoutId > 0) {
GLib.source_remove(this._timeoutId); Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0; this._timeoutId = 0;
} }
this._isPlaying = false; this._isPlaying = false;
} }
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
this.stop();
this._isLoaded = false;
this.destroy_all_children();
if (!validResourceScale) {
if (wasPlaying)
this.play();
return;
}
let textureCache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = textureCache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this._animations.set({
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
});
this.set_child(this._animations);
if (wasPlaying)
this.play();
}
_showFrame(frame) { _showFrame(frame) {
let oldFrameActor = this._animations.get_child_at_index(this._frame); let oldFrameActor = this._animations.get_child_at_index(this._frame);
if (oldFrameActor) if (oldFrameActor)
oldFrameActor.hide(); oldFrameActor.hide();
this._frame = frame % this._animations.get_n_children(); this._frame = (frame % this._animations.get_n_children());
let newFrameActor = this._animations.get_child_at_index(this._frame); let newFrameActor = this._animations.get_child_at_index(this._frame);
if (newFrameActor) if (newFrameActor)
@@ -100,56 +68,31 @@ class Animation extends St.Bin {
return GLib.SOURCE_CONTINUE; return GLib.SOURCE_CONTINUE;
} }
_syncAnimationSize() {
if (!this._isLoaded)
return;
let [width, height] = this.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() { _animationsLoaded() {
this._isLoaded = this._animations.get_n_children() > 0; this._isLoaded = this._animations.get_n_children() > 0;
this._syncAnimationSize();
if (this._isPlaying) if (this._isPlaying)
this.play(); this.play();
} }
_onDestroy() { _onDestroy() {
this.stop(); this.stop();
let themeContext = St.ThemeContext.get_for_stage(global.stage);
if (this._scaleChangedId)
themeContext.disconnect(this._scaleChangedId);
this._scaleChangedId = 0;
} }
}); };
var AnimatedIcon = GObject.registerClass( var AnimatedIcon = class extends Animation {
class AnimatedIcon extends Animation { constructor(file, size) {
_init(file, size) { super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
} }
}); };
var Spinner = GObject.registerClass( var Spinner = class extends AnimatedIcon {
class Spinner extends AnimatedIcon { constructor(size, animate=false) {
_init(size, params) {
params = Params.parse(params, {
animate: false,
hideOnStop: false,
});
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super._init(file, size); super(file, size);
this.opacity = 0; this.actor.opacity = 0;
this._animate = params.animate; this._animate = animate;
this._hideOnStop = params.hideOnStop;
this.visible = !this._hideOnStop;
} }
_onDestroy() { _onDestroy() {
@@ -158,43 +101,37 @@ class Spinner extends AnimatedIcon {
} }
play() { play() {
this.remove_all_transitions(); Tweener.removeTweens(this.actor);
this.show();
if (this._animate) { if (this._animate) {
super.play(); super.play();
this.ease({ Tweener.addTween(this.actor, {
opacity: 255, opacity: 255,
delay: SPINNER_ANIMATION_DELAY, delay: SPINNER_ANIMATION_DELAY,
duration: SPINNER_ANIMATION_TIME, time: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear'
}); });
} else { } else {
this.opacity = 255; this.actor.opacity = 255;
super.play(); super.play();
} }
} }
stop() { stop() {
this.remove_all_transitions(); Tweener.removeTweens(this.actor);
if (this._animate) { if (this._animate) {
this.ease({ Tweener.addTween(this.actor, {
opacity: 0, opacity: 0,
duration: SPINNER_ANIMATION_TIME, time: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR, transition: 'linear',
onComplete: () => { onComplete: () => {
super.stop(); this.stop(false);
if (this._hideOnStop) }
this.hide();
},
}); });
} else { } else {
this.opacity = 0; this.actor.opacity = 0;
super.stop(); super.stop();
if (this._hideOnStop)
this.hide();
} }
} }
}); };

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getAppFavorites */
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
@@ -15,48 +14,36 @@ const RENAMED_DESKTOP_IDS = {
'epiphany.desktop': 'org.gnome.Epiphany.desktop', 'epiphany.desktop': 'org.gnome.Epiphany.desktop',
'evolution.desktop': 'org.gnome.Evolution.desktop', 'evolution.desktop': 'org.gnome.Evolution.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.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', 'gcalctool.desktop': 'org.gnome.Calculator.desktop',
'geary.desktop': 'org.gnome.Geary.desktop', 'geary.desktop': 'org.gnome.Geary.desktop',
'gedit.desktop': 'org.gnome.gedit.desktop', 'gedit.desktop': 'org.gnome.gedit.desktop',
'glchess.desktop': 'org.gnome.Chess.desktop', 'glchess.desktop': 'gnome-chess.desktop',
'glines.desktop': 'org.gnome.five-or-more.desktop', 'glines.desktop': 'five-or-more.desktop',
'gnect.desktop': 'org.gnome.Four-in-a-row.desktop', 'gnect.desktop': 'four-in-a-row.desktop',
'gnibbles.desktop': 'org.gnome.Nibbles.desktop', 'gnibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnobots2.desktop': 'org.gnome.Robots.desktop', 'gnobots2.desktop': 'gnome-robots.desktop',
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop', 'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
'gnome-calculator.desktop': 'org.gnome.Calculator.desktop', 'gnome-calculator.desktop': 'org.gnome.Calculator.desktop',
'gnome-chess.desktop': 'org.gnome.Chess.desktop',
'gnome-clocks.desktop': 'org.gnome.clocks.desktop', 'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop', 'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
'gnome-documents.desktop': 'org.gnome.Documents.desktop', 'gnome-documents.desktop': 'org.gnome.Documents.desktop',
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.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-nibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnome-mahjongg.desktop': 'org.gnome.Mahjongg.desktop', 'gnome-mahjongg.desktop': 'org.gnome.Mahjongg.desktop',
'gnome-mines.desktop': 'org.gnome.Mines.desktop',
'gnome-music.desktop': 'org.gnome.Music.desktop', 'gnome-music.desktop': 'org.gnome.Music.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop', 'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-robots.desktop': 'org.gnome.Robots.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop', 'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop', 'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop', 'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
'gnome-tetravex.desktop': 'org.gnome.Tetravex.desktop',
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop', 'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.desktop', 'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
'gnomine.desktop': 'org.gnome.Mines.desktop', 'gnomine.desktop': 'gnome-mines.desktop',
'gnotravex.desktop': 'org.gnome.Tetravex.desktop', 'gnotravex.desktop': 'gnome-tetravex.desktop',
'gnotski.desktop': 'org.gnome.Klotski.desktop', 'gnotski.desktop': 'gnome-klotski.desktop',
'gtali.desktop': 'org.gnome.Tali.desktop', 'gtali.desktop': 'tali.desktop',
'iagno.desktop': 'org.gnome.Reversi.desktop', 'iagno.desktop': 'org.gnome.Iagno.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.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', 'polari.desktop': 'org.gnome.Polari.desktop',
'shotwell.desktop': 'org.gnome.Shotwell.desktop',
'tali.desktop': 'org.gnome.Tali.desktop',
'totem.desktop': 'org.gnome.Totem.desktop', 'totem.desktop': 'org.gnome.Totem.desktop',
'evince.desktop': 'org.gnome.Evince.desktop', 'evince.desktop': 'org.gnome.Evince.desktop',
}; };
@@ -65,7 +52,7 @@ class AppFavorites {
constructor() { constructor() {
this.FAVORITE_APPS_KEY = 'favorite-apps'; this.FAVORITE_APPS_KEY = 'favorite-apps';
this._favorites = {}; this._favorites = {};
global.settings.connect(`changed::${this.FAVORITE_APPS_KEY}`, this._onFavsChanged.bind(this)); global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, this._onFavsChanged.bind(this));
this.reload(); this.reload();
} }
@@ -148,10 +135,11 @@ class AppFavorites {
let app = Shell.AppSystem.get_default().lookup_app(appId); let app = Shell.AppSystem.get_default().lookup_app(appId);
let msg = _("%s has been added to your favorites.").format(app.get_name()); Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()),
Main.overview.setMessage(msg, { { forFeedback: true,
forFeedback: true, undoCallback: () => {
undoCallback: () => this._removeFavorite(appId), this._removeFavorite(appId);
}
}); });
} }
@@ -165,7 +153,7 @@ class AppFavorites {
} }
_removeFavorite(appId) { _removeFavorite(appId) {
if (!(appId in this._favorites)) if (!appId in this._favorites)
return false; return false;
let ids = this._getIds().filter(id => id != appId); let ids = this._getIds().filter(id => id != appId);
@@ -181,13 +169,14 @@ class AppFavorites {
if (!this._removeFavorite(appId)) if (!this._removeFavorite(appId))
return; return;
let msg = _("%s has been removed from your favorites.").format(app.get_name()); Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
Main.overview.setMessage(msg, { { forFeedback: true,
forFeedback: true, undoCallback: () => {
undoCallback: () => this._addFavorite(appId, pos), this._addFavorite(appId, pos);
}
}); });
} }
} };
Signals.addSignalMethods(AppFavorites.prototype); Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null; var appFavoritesInstance = null;

View File

@@ -1,5 +1,9 @@
/* exported AudioDeviceSelectionDBus */ const Clutter = imports.gi.Clutter;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
@@ -9,16 +13,15 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
var AudioDevice = { var AudioDevice = {
HEADPHONES: 1 << 0, HEADPHONES: 1 << 0,
HEADSET: 1 << 1, HEADSET: 1 << 1,
MICROPHONE: 1 << 2, MICROPHONE: 1 << 2
}; };
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection'); const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
var AudioDeviceSelectionDialog = GObject.registerClass({ var AudioDeviceSelectionDialog =
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } }, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog { constructor(devices) {
_init(devices) { super({ styleClass: 'audio-device-selection-dialog' });
super._init({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {}; this._deviceItems = {};
@@ -35,7 +38,11 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
throw new Error('Too few devices for a selection'); throw new Error('Too few devices for a selection');
} }
_buildLayout() { destroy() {
super.destroy();
}
_buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title', let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"), text: _("Select Audio Device"),
x_align: Clutter.ActorAlign.CENTER }); x_align: Clutter.ActorAlign.CENTER });
@@ -43,23 +50,19 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
this.contentLayout.style_class = 'audio-selection-content'; this.contentLayout.style_class = 'audio-selection-content';
this.contentLayout.add(title); this.contentLayout.add(title);
this._selectionBox = new St.BoxLayout({ this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
style_class: 'audio-selection-box', this.contentLayout.add(this._selectionBox, { expand: true });
x_expand: true,
});
this.contentLayout.add_child(this._selectionBox);
if (Main.sessionMode.allowSettings) { if (Main.sessionMode.allowSettings)
this.addButton({ action: this._openSettings.bind(this), this.addButton({ action: this._openSettings.bind(this),
label: _("Sound Settings") }); label: _("Sound Settings") });
}
this.addButton({ action: this.close.bind(this), this.addButton({ action: this.close.bind(this),
label: _("Cancel"), label: _("Cancel"),
key: Clutter.KEY_Escape }); key: Clutter.Escape });
} }
_getDeviceLabel(device) { _getDeviceLabel(device) {
switch (device) { switch(device) {
case AudioDevice.HEADPHONES: case AudioDevice.HEADPHONES:
return _("Headphones"); return _("Headphones");
case AudioDevice.HEADSET: case AudioDevice.HEADSET:
@@ -72,7 +75,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
} }
_getDeviceIcon(device) { _getDeviceIcon(device) {
switch (device) { switch(device) {
case AudioDevice.HEADPHONES: case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic'; return 'audio-headphones-symbolic';
case AudioDevice.HEADSET: case AudioDevice.HEADSET:
@@ -90,7 +93,6 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
box.connect('notify::height', () => { box.connect('notify::height', () => {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
box.width = box.height; box.width = box.height;
return GLib.SOURCE_REMOVE;
}); });
}); });
@@ -116,11 +118,11 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
} }
_openSettings() { _openSettings() {
let desktopFile = 'gnome-sound-panel.desktop'; let desktopFile = 'gnome-sound-panel.desktop'
let app = Shell.AppSystem.get_default().lookup_app(desktopFile); let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
if (!app) { if (!app) {
log(`Settings panel for desktop file ${desktopFile} could not be loaded!`); log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
return; return;
} }
@@ -128,7 +130,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
Main.overview.hide(); Main.overview.hide();
app.activate(); app.activate();
} }
}); };
var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus { var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
constructor() { constructor() {
@@ -165,12 +167,12 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
let [deviceNames] = params; let [deviceNames] = params;
let devices = 0; let devices = 0;
deviceNames.forEach(n => (devices |= AudioDevice[n.toUpperCase()])); deviceNames.forEach(n => { devices |= AudioDevice[n.toUpperCase()]; });
let dialog; let dialog;
try { try {
dialog = new AudioDeviceSelectionDialog(devices); dialog = new AudioDeviceSelectionDialog(devices);
} catch (e) { } catch(e) {
invocation.return_value(null); invocation.return_value(null);
return; return;
} }

View File

@@ -1,5 +1,4 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SystemBackground */
// READ THIS FIRST // READ THIS FIRST
// Background handling is a maze of objects, both objects in this file, and // Background handling is a maze of objects, both objects in this file, and
@@ -94,12 +93,18 @@
// MetaBackgroundImage MetaBackgroundImage // MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage // MetaBackgroundImage MetaBackgroundImage
const { Clutter, GDesktopEnums, Gio, GLib, GObject, GnomeDesktop, Meta } = imports.gi; const Clutter = imports.gi.Clutter;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Meta = imports.gi.Meta;
const Signals = imports.signals; const Signals = imports.signals;
const LoginManager = imports.misc.loginManager; const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff); var DEFAULT_BACKGROUND_COLOR = Clutter.Color.from_pixel(0x2e3436ff);
@@ -108,9 +113,10 @@ const PRIMARY_COLOR_KEY = 'primary-color';
const SECONDARY_COLOR_KEY = 'secondary-color'; const SECONDARY_COLOR_KEY = 'secondary-color';
const COLOR_SHADING_TYPE_KEY = 'color-shading-type'; const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
const BACKGROUND_STYLE_KEY = 'picture-options'; const BACKGROUND_STYLE_KEY = 'picture-options';
const PICTURE_OPACITY_KEY = 'picture-opacity';
const PICTURE_URI_KEY = 'picture-uri'; const PICTURE_URI_KEY = 'picture-uri';
var FADE_ANIMATION_TIME = 1000; var FADE_ANIMATION_TIME = 1.0;
// These parameters affect how often we redraw. // These parameters affect how often we redraw.
// The first is how different (percent crossfaded) the slide show // The first is how different (percent crossfaded) the slide show
@@ -145,7 +151,7 @@ var BackgroundCache = class BackgroundCache {
let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null); let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', monitor.connect('changed',
(obj, theFile, otherFile, eventType) => { (obj, file, otherFile, eventType) => {
// Ignore CHANGED and CREATED events, since in both cases // Ignore CHANGED and CREATED events, since in both cases
// we'll get a CHANGES_DONE_HINT event when done. // we'll get a CHANGES_DONE_HINT event when done.
if (eventType != Gio.FileMonitorEvent.CHANGED && if (eventType != Gio.FileMonitorEvent.CHANGED &&
@@ -221,17 +227,16 @@ function getBackgroundCache() {
return _backgroundCache; return _backgroundCache;
} }
var Background = GObject.registerClass({ var Background = class Background {
Signals: { 'loaded': {}, 'bg-changed': {} }, constructor(params) {
}, class Background extends Meta.Background {
_init(params) {
params = Params.parse(params, { monitorIndex: 0, params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager, layoutManager: Main.layoutManager,
settings: null, settings: null,
file: null, file: null,
style: null }); style: null });
super._init({ meta_display: global.display }); this.background = new Meta.Background({ meta_display: global.display });
this.background._delegate = this;
this._settings = params.settings; this._settings = params.settings;
this._file = params.file; this._file = params.file;
@@ -257,8 +262,9 @@ var Background = GObject.registerClass({
this._refreshAnimation(); this._refreshAnimation();
}); });
this._settingsChangedSignalId = this._settingsChangedSignalId = this._settings.connect('changed', () => {
this._settings.connect('changed', this._emitChangedSignal.bind(this)); this.emit('changed');
});
this._load(); this._load();
} }
@@ -269,9 +275,9 @@ var Background = GObject.registerClass({
let i; let i;
let keys = Object.keys(this._fileWatches); let keys = Object.keys(this._fileWatches);
for (i = 0; i < keys.length; i++) for (i = 0; i < keys.length; i++) {
this._cache.disconnect(this._fileWatches[keys[i]]); this._cache.disconnect(this._fileWatches[keys[i]]);
}
this._fileWatches = null; this._fileWatches = null;
if (this._timezoneChangedId != 0) if (this._timezoneChangedId != 0)
@@ -287,24 +293,6 @@ var Background = GObject.registerClass({
if (this._settingsChangedSignalId != 0) if (this._settingsChangedSignalId != 0)
this._settings.disconnect(this._settingsChangedSignalId); this._settings.disconnect(this._settingsChangedSignalId);
this._settingsChangedSignalId = 0; this._settingsChangedSignalId = 0;
if (this._changedIdleId) {
GLib.source_remove(this._changedIdleId);
this._changedIdleId = 0;
}
}
_emitChangedSignal() {
if (this._changedIdleId)
return;
this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._changedIdleId = 0;
this.emit('bg-changed');
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._changedIdleId,
'[gnome-shell] Background._emitChangedSignal');
} }
updateResolution() { updateResolution() {
@@ -330,23 +318,23 @@ var Background = GObject.registerClass({
this.emit('loaded'); this.emit('loaded');
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] Background._setLoaded Idle'); GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
} }
_loadPattern() { _loadPattern() {
let colorString, res_, color, secondColor; let colorString, res, color, secondColor;
colorString = this._settings.get_string(PRIMARY_COLOR_KEY); colorString = this._settings.get_string(PRIMARY_COLOR_KEY);
[res_, color] = Clutter.Color.from_string(colorString); [res, color] = Clutter.Color.from_string(colorString);
colorString = this._settings.get_string(SECONDARY_COLOR_KEY); colorString = this._settings.get_string(SECONDARY_COLOR_KEY);
[res_, secondColor] = Clutter.Color.from_string(colorString); [res, secondColor] = Clutter.Color.from_string(colorString);
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY); let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
if (shadingType == GDesktopEnums.BackgroundShading.SOLID) if (shadingType == GDesktopEnums.BackgroundShading.SOLID)
this.set_color(color); this.background.set_color(color);
else else
this.set_gradient(shadingType, color, secondColor); this.background.set_gradient(shadingType, color, secondColor);
} }
_watchFile(file) { _watchFile(file) {
@@ -360,7 +348,7 @@ var Background = GObject.registerClass({
if (changedFile.equal(file)) { if (changedFile.equal(file)) {
let imageCache = Meta.BackgroundImageCache.get_default(); let imageCache = Meta.BackgroundImageCache.get_default();
imageCache.purge(changedFile); imageCache.purge(changedFile);
this._emitChangedSignal(); this.emit('changed');
} }
}); });
this._fileWatches[key] = signalId; this._fileWatches[key] = signalId;
@@ -382,13 +370,13 @@ var Background = GObject.registerClass({
let finish = () => { let finish = () => {
this._setLoaded(); this._setLoaded();
if (files.length > 1) { if (files.length > 1) {
this.set_blend(files[0], files[1], this.background.set_blend(files[0], files[1],
this._animation.transitionProgress, this._animation.transitionProgress,
this._style); this._style);
} else if (files.length > 0) { } else if (files.length > 0) {
this.set_file(files[0], this._style); this.background.set_file(files[0], this._style);
} else { } else {
this.set_file(null, this._style); this.background.set_file(null, this._style);
} }
this._queueUpdateAnimation(); this._queueUpdateAnimation();
}; };
@@ -403,7 +391,6 @@ var Background = GObject.registerClass({
if (numPendingImages == 0) if (numPendingImages == 0)
finish(); finish();
} else { } else {
// eslint-disable-next-line no-loop-func
let id = image.connect('loaded', () => { let id = image.connect('loaded', () => {
image.disconnect(id); image.disconnect(id);
numPendingImages--; numPendingImages--;
@@ -444,8 +431,7 @@ var Background = GObject.registerClass({
} }
_loadAnimation(file) { _loadAnimation(file) {
this._cache.getAnimation({ this._cache.getAnimation({ file: file,
file,
settingsSchema: this._settings.schema_id, settingsSchema: this._settings.schema_id,
onLoaded: animation => { onLoaded: animation => {
this._animation = animation; this._animation = animation;
@@ -457,19 +443,19 @@ var Background = GObject.registerClass({
this._updateAnimation(); this._updateAnimation();
this._watchFile(file); this._watchFile(file);
}, }
}); });
} }
_loadImage(file) { _loadImage(file) {
this.set_file(file, this._style); this.background.set_file(file, this._style);
this._watchFile(file); this._watchFile(file);
let cache = Meta.BackgroundImageCache.get_default(); let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file); let image = cache.load(file);
if (image.is_loaded()) { if (image.is_loaded())
this._setLoaded(); this._setLoaded();
} else { else {
let id = image.connect('loaded', () => { let id = image.connect('loaded', () => {
this._setLoaded(); this._setLoaded();
image.disconnect(id); image.disconnect(id);
@@ -496,14 +482,13 @@ var Background = GObject.registerClass({
this._loadFile(this._file); this._loadFile(this._file);
} }
}); };
Signals.addSignalMethods(Background.prototype);
let _systemBackground; let _systemBackground;
var SystemBackground = GObject.registerClass({ var SystemBackground = class SystemBackground {
Signals: { 'loaded': {} }, constructor() {
}, class SystemBackground extends Meta.BackgroundActor {
_init() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png'); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
if (_systemBackground == null) { if (_systemBackground == null) {
@@ -512,11 +497,9 @@ var SystemBackground = GObject.registerClass({
_systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER); _systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER);
} }
super._init({ this.actor = new Meta.BackgroundActor({ meta_display: global.display,
meta_display: global.display,
monitor: 0, monitor: 0,
background: _systemBackground, background: _systemBackground });
});
let cache = Meta.BackgroundImageCache.get_default(); let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file); let image = cache.load(file);
@@ -535,7 +518,8 @@ var SystemBackground = GObject.registerClass({
}); });
} }
} }
}); };
Signals.addSignalMethods(SystemBackground.prototype);
var BackgroundSource = class BackgroundSource { var BackgroundSource = class BackgroundSource {
constructor(layoutManager, settingsSchema) { constructor(layoutManager, settingsSchema) {
@@ -571,7 +555,7 @@ var BackgroundSource = class BackgroundSource {
// We don't watch changes to settings here, // We don't watch changes to settings here,
// instead we rely on Background to watch those // instead we rely on Background to watch those
// and emit 'bg-changed' at the right time // and emit 'changed' at the right time
if (this._overrideImage != null) { if (this._overrideImage != null) {
file = Gio.File.new_for_path(this._overrideImage); file = Gio.File.new_for_path(this._overrideImage);
@@ -593,14 +577,14 @@ var BackgroundSource = class BackgroundSource {
if (!(monitorIndex in this._backgrounds)) { if (!(monitorIndex in this._backgrounds)) {
let background = new Background({ let background = new Background({
monitorIndex, monitorIndex: monitorIndex,
layoutManager: this._layoutManager, layoutManager: this._layoutManager,
settings: this._settings, settings: this._settings,
file, file: file,
style, style: style
}); });
background._changedId = background.connect('bg-changed', () => { background._changedId = background.connect('changed', () => {
background.disconnect(background._changedId); background.disconnect(background._changedId);
background.destroy(); background.destroy();
delete this._backgrounds[monitorIndex]; delete this._backgrounds[monitorIndex];
@@ -626,11 +610,11 @@ var BackgroundSource = class BackgroundSource {
} }
}; };
var Animation = GObject.registerClass( var Animation = class Animation {
class Animation extends GnomeDesktop.BGSlideShow { constructor(params) {
_init(params) { params = Params.parse(params, { file: null });
super._init(params);
this.file = params.file;
this.keyFrameFiles = []; this.keyFrameFiles = [];
this.transitionProgress = 0.0; this.transitionProgress = 0.0;
this.transitionDuration = 0.0; this.transitionDuration = 0.0;
@@ -638,7 +622,9 @@ class Animation extends GnomeDesktop.BGSlideShow {
} }
load(callback) { load(callback) {
this.load_async(null, () => { this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
this._show.load_async(null, (object, result) => {
this.loaded = true; this.loaded = true;
if (callback) if (callback)
callback(); callback();
@@ -648,11 +634,13 @@ class Animation extends GnomeDesktop.BGSlideShow {
update(monitor) { update(monitor) {
this.keyFrameFiles = []; this.keyFrameFiles = [];
if (this.get_num_slides() < 1) if (!this._show)
return; return;
let [progress, duration, isFixed_, filename1, filename2] = if (this._show.get_num_slides() < 1)
this.get_current_slide(monitor.width, monitor.height); return;
let [progress, duration, isFixed, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height);
this.transitionDuration = duration; this.transitionDuration = duration;
this.transitionProgress = progress; this.transitionProgress = progress;
@@ -663,7 +651,8 @@ class Animation extends GnomeDesktop.BGSlideShow {
if (filename2) if (filename2)
this.keyFrameFiles.push(Gio.File.new_for_path(filename2)); this.keyFrameFiles.push(Gio.File.new_for_path(filename2));
} }
}); };
Signals.addSignalMethods(Animation.prototype);
var BackgroundManager = class BackgroundManager { var BackgroundManager = class BackgroundManager {
constructor(params) { constructor(params) {
@@ -710,11 +699,14 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = null; this._newBackgroundActor = null;
this.emit('changed'); this.emit('changed');
oldBackgroundActor.ease({ Tweener.addTween(oldBackgroundActor,
opacity: 0, { opacity: 0,
duration: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, transition: 'easeOutQuad',
onComplete: () => oldBackgroundActor.destroy(), onComplete() {
oldBackgroundActor.background.run_dispose();
oldBackgroundActor.destroy();
}
}); });
} }
@@ -732,7 +724,7 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = newBackgroundActor; this._newBackgroundActor = newBackgroundActor;
let background = newBackgroundActor.background; let background = newBackgroundActor.background._delegate;
if (background.isLoaded) { if (background.isLoaded) {
this._swapBackgroundActor(); this._swapBackgroundActor();
@@ -749,10 +741,9 @@ var BackgroundManager = class BackgroundManager {
_createBackgroundActor() { _createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex); let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new Meta.BackgroundActor({ let backgroundActor = new Meta.BackgroundActor({ meta_display: global.display,
meta_display: global.display,
monitor: this._monitorIndex, monitor: this._monitorIndex,
background, background: background.background,
vignette: this._vignette, vignette: this._vignette,
vignette_sharpness: 0.5, vignette_sharpness: 0.5,
brightness: 0.5, brightness: 0.5,
@@ -760,13 +751,15 @@ var BackgroundManager = class BackgroundManager {
this._container.add_child(backgroundActor); this._container.add_child(backgroundActor);
if (this._controlPosition) {
let monitor = this._layoutManager.monitors[this._monitorIndex]; let monitor = this._layoutManager.monitors[this._monitorIndex];
backgroundActor.set_size(monitor.width, monitor.height);
if (this._controlPosition) {
backgroundActor.set_position(monitor.x, monitor.y); backgroundActor.set_position(monitor.x, monitor.y);
this._container.set_child_below_sibling(backgroundActor, null); backgroundActor.lower_bottom();
} }
let changeSignalId = background.connect('bg-changed', () => { let changeSignalId = background.connect('changed', () => {
background.disconnect(changeSignalId); background.disconnect(changeSignalId);
changeSignalId = null; changeSignalId = null;
this._updateBackgroundActor(); this._updateBackgroundActor();

View File

@@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addBackgroundMenu */
const { Clutter, St } = imports.gi; const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -26,21 +27,20 @@ var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu {
function addBackgroundMenu(actor, layoutManager) { function addBackgroundMenu(actor, layoutManager) {
actor.reactive = true; actor.reactive = true;
actor._backgroundMenu = new BackgroundMenu(layoutManager); actor._backgroundMenu = new BackgroundMenu(layoutManager);
actor._backgroundManager = new PopupMenu.PopupMenuManager(actor); actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
actor._backgroundManager.addMenu(actor._backgroundMenu); actor._backgroundManager.addMenu(actor._backgroundMenu);
function openMenu(x, y) { function openMenu(x, y) {
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0); Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.FULL); actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
} }
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', (action, theActor, state) => { clickAction.connect('long-press', (action, actor, state) => {
if (state == Clutter.LongPressState.QUERY) { if (state == Clutter.LongPressState.QUERY)
return (action.get_button() == 0 || return ((action.get_button() == 0 ||
action.get_button() == 1) && action.get_button() == 1) &&
!actor._backgroundMenu.isOpen; !actor._backgroundMenu.isOpen);
}
if (state == Clutter.LongPressState.ACTIVATE) { if (state == Clutter.LongPressState.ACTIVATE) {
let [x, y] = action.get_coords(); let [x, y] = action.get_coords();
openMenu(x, y); openMenu(x, y);

View File

@@ -1,107 +1,77 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported BarLevel */
const { Atk, Clutter, GObject, St } = imports.gi; const Atk = imports.gi.Atk;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Signals = imports.signals;
var BarLevel = GObject.registerClass({ var BarLevel = class {
Properties: { constructor(value, params) {
'value': GObject.ParamSpec.double( if (isNaN(value))
'value', 'value', 'value', // Avoid spreading NaNs around
GObject.ParamFlags.READWRITE, throw TypeError('The bar level value must be a number');
0, 2, 0),
'maximum-value': GObject.ParamSpec.double(
'maximum-value', 'maximum-value', 'maximum-value',
GObject.ParamFlags.READWRITE,
1, 2, 1),
'overdrive-start': GObject.ParamSpec.double(
'overdrive-start', 'overdrive-start', 'overdrive-start',
GObject.ParamFlags.READWRITE,
1, 2, 1),
},
}, class BarLevel extends St.DrawingArea {
_init(params) {
this._maxValue = 1; this._maxValue = 1;
this._value = 0; this._value = Math.max(Math.min(value, this._maxValue), 0);
this._overdriveStart = 1; this._overdriveStart = 1;
this._barLevelWidth = 0; this._barLevelWidth = 0;
let defaultParams = { if (params == undefined)
style_class: 'barlevel', params = {}
accessible_role: Atk.Role.LEVEL_BAR,
}; this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
super._init(Object.assign(defaultParams, params)); can_focus: params['canFocus'] || false,
this.connect('allocation-changed', (actor, box) => { reactive: params['reactive'] || false,
accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
this.actor.connect('repaint', this._barLevelRepaint.bind(this));
this.actor.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width(); this._barLevelWidth = box.get_width();
}); });
this._customAccessible = St.GenericAccessible.new_for_actor(this); this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.set_accessible(this._customAccessible); this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this)); this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this)); this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this)); this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this)); this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('notify::value', this._valueChanged.bind(this)); this.connect('value-changed', this._valueChanged.bind(this));
} }
get value() { setValue(value) {
return this._value; if (isNaN(value))
throw TypeError('The bar level value must be a number');
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
} }
set value(value) { setMaximumValue(value) {
value = Math.max(Math.min(value, this._maxValue), 0); if (isNaN(value))
throw TypeError('The bar level max value must be a number');
if (this._value == value) this._maxValue = Math.max(value, 1);
return;
this._value = value;
this.notify('value');
this.queue_repaint();
}
// eslint-disable-next-line camelcase
get maximum_value() {
return this._maxValue;
}
// eslint-disable-next-line camelcase
set maximum_value(value) {
value = Math.max(value, 1);
if (this._maxValue == value)
return;
this._maxValue = value;
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue); this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.notify('maximum-value'); this.actor.queue_repaint();
this.queue_repaint();
} }
// eslint-disable-next-line camelcase setOverdriveStart(value) {
get overdrive_start() { if (isNaN(value))
return this._overdriveStart; throw TypeError('The overdrive limit value must be a number');
} if (value > this._maxValue)
// eslint-disable-next-line camelcase
set overdrive_start(value) {
if (this._overdriveStart == value)
return;
if (value > this._maxValue) {
throw new Error(`Tried to set overdrive value to ${value}, ` + throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`); `which is a number greater than the maximum allowed value ${this._maxValue}`);
}
this._overdriveStart = value; this._overdriveStart = value;
this.notify('overdrive-start'); this._value = Math.max(Math.min(value, this._maxValue), 0);
this.queue_repaint(); this.actor.queue_repaint();
} }
vfunc_repaint() { _barLevelRepaint(area) {
let cr = this.get_context(); let cr = area.get_context();
let themeNode = this.get_theme_node(); let themeNode = area.get_theme_node();
let [width, height] = this.get_surface_size(); let [width, height] = area.get_surface_size();
let barLevelHeight = themeNode.get_length('-barlevel-height'); let barLevelHeight = themeNode.get_length('-barlevel-height');
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2; let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
@@ -138,7 +108,7 @@ var BarLevel = GObject.registerClass({
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width'); overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
/* background bar */ /* background bar */
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4)); cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(endX, (height + barLevelHeight) / 2); cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2); cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2); cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
@@ -150,11 +120,10 @@ var BarLevel = GObject.registerClass({
/* normal progress bar */ /* normal progress bar */
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2); let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (1 / 4), TAU * (3 / 4)); cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
cr.lineTo(x, (height - barLevelHeight) / 2); cr.lineTo(x, (height - barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2); cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2); cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
if (this._value > 0)
Clutter.cairo_set_source_color(cr, barLevelActiveColor); Clutter.cairo_set_source_color(cr, barLevelActiveColor);
cr.fillPreserve(); cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor); Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
@@ -177,19 +146,17 @@ var BarLevel = GObject.registerClass({
} }
/* end progress bar arc */ /* end progress bar arc */
if (this._value > 0) {
if (this._value <= this._overdriveStart) if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor); Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor); Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4)); cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2); cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2); cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2); cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve(); cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth); cr.setLineWidth(barLevelBorderWidth);
cr.stroke(); cr.stroke();
}
/* draw overdrive separator */ /* draw overdrive separator */
if (overdriveActive) { if (overdriveActive) {
@@ -208,27 +175,32 @@ var BarLevel = GObject.registerClass({
cr.$dispose(); cr.$dispose();
} }
_getCurrentValue() { _getCurrentValue(actor) {
return this._value; return this._value;
} }
_getOverdriveStart() { _getOverdriveStart(actor) {
return this._overdriveStart; return this._overdriveStart;
} }
_getMinimumValue() { _getMinimumValue(actor) {
return 0; return 0;
} }
_getMaximumValue() { _getMaximumValue(actor) {
return this._maxValue; return this._maxValue;
} }
_setCurrentValue(_actor, value) { _setCurrentValue(actor, value) {
this._value = value; this._value = value;
} }
_valueChanged() { _valueChanged(barLevel, value, property) {
this._customAccessible.notify("accessible-value"); this._customAccessible.notify("accessible-value");
} }
});
get value() {
return this._value;
}
};
Signals.addSignalMethods(BarLevel.prototype);

View File

@@ -1,9 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BoxPointer */
const { Clutter, GObject, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const GObject = imports.gi.GObject;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
var PopupAnimation = { var PopupAnimation = {
NONE: 0, NONE: 0,
@@ -12,7 +17,7 @@ var PopupAnimation = {
FULL: ~0, FULL: ~0,
}; };
var POPUP_ANIMATION_TIME = 150; var POPUP_ANIMATION_TIME = 0.15;
/** /**
* BoxPointer: * BoxPointer:
@@ -24,7 +29,7 @@ var POPUP_ANIMATION_TIME = 150;
* placed. The arrow position may be controlled via * placed. The arrow position may be controlled via
* setArrowOrigin(). The arrow side might be temporarily flipped * setArrowOrigin(). The arrow side might be temporarily flipped
* depending on the box size and source position to keep the box * depending on the box size and source position to keep the box
* totally inside the monitor workarea if possible. * totally inside the monitor if possible.
* *
*/ */
var BoxPointer = GObject.registerClass({ var BoxPointer = GObject.registerClass({
@@ -33,6 +38,8 @@ var BoxPointer = GObject.registerClass({
_init(arrowSide, binProperties) { _init(arrowSide, binProperties) {
super._init(); super._init();
this.actor = this;
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
@@ -44,35 +51,67 @@ var BoxPointer = GObject.registerClass({
this._border = new St.DrawingArea(); this._border = new St.DrawingArea();
this._border.connect('repaint', this._drawBorder.bind(this)); this._border.connect('repaint', this._drawBorder.bind(this));
this.add_actor(this._border); this.add_actor(this._border);
this.set_child_above_sibling(this.bin, this._border); this.bin.raise(this._border);
this._xOffset = 0;
this._yOffset = 0;
this._xPosition = 0;
this._yPosition = 0;
this._sourceAlignment = 0.5; this._sourceAlignment = 0.5;
this._muteInput = true; this._capturedEventId = 0;
this._muteInput();
this.connect('destroy', this._onDestroy.bind(this));
}
vfunc_captured_event() {
if (this._muteInput)
return Clutter.EVENT_STOP;
return Clutter.EVENT_PROPAGATE;
}
_onDestroy() {
if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId);
delete this._sourceActorDestroyId;
}
} }
get arrowSide() { get arrowSide() {
return this._arrowSide; return this._arrowSide;
} }
_muteInput() {
if (this._capturedEventId == 0)
this._capturedEventId = this.connect('captured-event',
() => Clutter.EVENT_STOP);
}
_unmuteInput() {
if (this._capturedEventId != 0) {
this.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
}
// BoxPointer.show() and BoxPointer.hide() are here for only compatibility
// purposes, and will be removed in 3.32.
show(animate, onComplete) {
if (animate !== undefined) {
try {
throw new Error('BoxPointer.show() has been moved to BoxPointer.open(), this code will break in the future.');
} catch(e) {
logError(e);
this.open(animate, onComplete);
return;
}
}
this.visible = true;
}
hide(animate, onComplete) {
if (animate !== undefined) {
try {
throw new Error('BoxPointer.hide() has been moved to BoxPointer.close(), this code will break in the future.');
} catch(e) {
logError(e);
this.close(animate, onComplete);
return;
}
}
this.visible = false;
}
open(animate, onComplete) { open(animate, onComplete) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
let animationTime = animate & PopupAnimation.FULL ? POPUP_ANIMATION_TIME : 0; let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
if (animate & PopupAnimation.FADE) if (animate & PopupAnimation.FADE)
this.opacity = 0; this.opacity = 0;
@@ -84,79 +123,76 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) { if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) { switch (this._arrowSide) {
case St.Side.TOP: case St.Side.TOP:
this.translation_y = -rise; this.yOffset = -rise;
break; break;
case St.Side.BOTTOM: case St.Side.BOTTOM:
this.translation_y = rise; this.yOffset = rise;
break; break;
case St.Side.LEFT: case St.Side.LEFT:
this.translation_x = -rise; this.xOffset = -rise;
break; break;
case St.Side.RIGHT: case St.Side.RIGHT:
this.translation_x = rise; this.xOffset = rise;
break; break;
} }
} }
this.ease({ Tweener.addTween(this, { opacity: 255,
opacity: 255, xOffset: 0,
translation_x: 0, yOffset: 0,
translation_y: 0, transition: 'linear',
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => { onComplete: () => {
this._muteInput = false; this._unmuteInput();
if (onComplete) if (onComplete)
onComplete(); onComplete();
}, },
}); time: animationTime });
} }
close(animate, onComplete) { close(animate, onComplete) {
if (!this.visible) if (!this.visible)
return; return;
let translationX = 0; let xOffset = 0;
let translationY = 0; let yOffset = 0;
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
let fade = animate & PopupAnimation.FADE; let fade = (animate & PopupAnimation.FADE);
let animationTime = animate & PopupAnimation.FULL ? POPUP_ANIMATION_TIME : 0; let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
if (animate & PopupAnimation.SLIDE) { if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) { switch (this._arrowSide) {
case St.Side.TOP: case St.Side.TOP:
translationY = rise; yOffset = rise;
break; break;
case St.Side.BOTTOM: case St.Side.BOTTOM:
translationY = -rise; yOffset = -rise;
break; break;
case St.Side.LEFT: case St.Side.LEFT:
translationX = rise; xOffset = rise;
break; break;
case St.Side.RIGHT: case St.Side.RIGHT:
translationX = -rise; xOffset = -rise;
break; break;
} }
} }
this._muteInput = true; this._muteInput();
this.remove_all_transitions(); Tweener.removeTweens(this);
this.ease({ Tweener.addTween(this, { opacity: fade ? 0 : 255,
opacity: fade ? 0 : 255, xOffset: xOffset,
translation_x: translationX, yOffset: yOffset,
translation_y: translationY, transition: 'linear',
duration: animationTime, time: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => { onComplete: () => {
this.hide(); this.hide();
this.opacity = 0; this.opacity = 0;
this.translation_x = 0; this.xOffset = 0;
this.translation_y = 0; this.yOffset = 0;
if (onComplete) if (onComplete)
onComplete(); onComplete();
}, }
}); });
} }
@@ -165,8 +201,8 @@ var BoxPointer = GObject.registerClass({
let borderWidth = themeNode.get_length('-arrow-border-width'); let borderWidth = themeNode.get_length('-arrow-border-width');
minSize += borderWidth * 2; minSize += borderWidth * 2;
natSize += borderWidth * 2; natSize += borderWidth * 2;
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)) || if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
(isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) { || (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
minSize += rise; minSize += rise;
natSize += rise; natSize += rise;
@@ -200,10 +236,13 @@ var BoxPointer = GObject.registerClass({
this.set_allocation(box, flags); this.set_allocation(box, flags);
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
let borderWidth = themeNode.get_length('-arrow-border-width'); let borderWidth = themeNode.get_length('-arrow-border-width');
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
let [availWidth, availHeight] = themeNode.get_content_box(box).get_size(); let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
childBox.x1 = 0; childBox.x1 = 0;
childBox.y1 = 0; childBox.y1 = 0;
@@ -232,9 +271,8 @@ var BoxPointer = GObject.registerClass({
this.bin.allocate(childBox, flags); this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) { if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(box); this._reposition();
this._updateFlip(box); this._updateFlip();
this.set_allocation(box, flags);
} }
} }
@@ -247,11 +285,12 @@ var BoxPointer = GObject.registerClass({
let [absX, absY] = this.get_transformed_position(); let [absX, absY] = this.get_transformed_position();
if (this._arrowSide == St.Side.TOP || if (this._arrowSide == St.Side.TOP ||
this._arrowSide == St.Side.BOTTOM) this._arrowSide == St.Side.BOTTOM) {
this._arrowOrigin = sourceX - absX + sourceWidth / 2; this._arrowOrigin = sourceX - absX + sourceWidth / 2;
else } else {
this._arrowOrigin = sourceY - absY + sourceHeight / 2; this._arrowOrigin = sourceY - absY + sourceHeight / 2;
} }
}
let borderWidth = themeNode.get_length('-arrow-border-width'); let borderWidth = themeNode.get_length('-arrow-border-width');
let base = themeNode.get_length('-arrow-base'); let base = themeNode.get_length('-arrow-base');
@@ -259,25 +298,26 @@ var BoxPointer = GObject.registerClass({
let borderRadius = themeNode.get_length('-arrow-border-radius'); let borderRadius = themeNode.get_length('-arrow-border-radius');
let halfBorder = borderWidth / 2; let halfBorder = borderWidth / 2;
let halfBase = Math.floor(base / 2); let halfBase = Math.floor(base/2);
let backgroundColor = themeNode.get_color('-arrow-background-color'); let backgroundColor = themeNode.get_color('-arrow-background-color');
let [width, height] = area.get_surface_size(); let [width, height] = area.get_surface_size();
let [boxWidth, boxHeight] = [width, height]; let [boxWidth, boxHeight] = [width, height];
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) {
boxHeight -= rise; boxHeight -= rise;
else } else {
boxWidth -= rise; boxWidth -= rise;
}
let cr = area.get_context(); let cr = area.get_context();
// Translate so that box goes from 0,0 to boxWidth,boxHeight, // Translate so that box goes from 0,0 to boxWidth,boxHeight,
// with the arrow poking out of that // with the arrow poking out of that
if (this._arrowSide == St.Side.TOP) if (this._arrowSide == St.Side.TOP) {
cr.translate(0, rise); cr.translate(0, rise);
else if (this._arrowSide == St.Side.LEFT) } else if (this._arrowSide == St.Side.LEFT) {
cr.translate(rise, 0); cr.translate(rise, 0);
}
let [x1, y1] = [halfBorder, halfBorder]; let [x1, y1] = [halfBorder, halfBorder];
let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder]; let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
@@ -339,7 +379,7 @@ var BoxPointer = GObject.registerClass({
if (!skipTopRight) { if (!skipTopRight) {
cr.lineTo(x2 - borderRadius, y1); cr.lineTo(x2 - borderRadius, y1);
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius, cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
3 * Math.PI / 2, Math.PI * 2); 3*Math.PI/2, Math.PI*2);
} }
if (this._arrowSide == St.Side.RIGHT && rise) { if (this._arrowSide == St.Side.RIGHT && rise) {
@@ -360,7 +400,7 @@ var BoxPointer = GObject.registerClass({
if (!skipBottomRight) { if (!skipBottomRight) {
cr.lineTo(x2, y2 - borderRadius); cr.lineTo(x2, y2 - borderRadius);
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius, cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
0, Math.PI / 2); 0, Math.PI/2);
} }
if (this._arrowSide == St.Side.BOTTOM && rise) { if (this._arrowSide == St.Side.BOTTOM && rise) {
@@ -381,7 +421,7 @@ var BoxPointer = GObject.registerClass({
if (!skipBottomLeft) { if (!skipBottomLeft) {
cr.lineTo(x1 + borderRadius, y2); cr.lineTo(x1 + borderRadius, y2);
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius, cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
Math.PI / 2, Math.PI); Math.PI/2, Math.PI);
} }
if (this._arrowSide == St.Side.LEFT && rise) { if (this._arrowSide == St.Side.LEFT && rise) {
@@ -390,7 +430,7 @@ var BoxPointer = GObject.registerClass({
cr.lineTo(x1 - rise, y1); cr.lineTo(x1 - rise, y1);
cr.lineTo(x1 + borderRadius, y1); cr.lineTo(x1 + borderRadius, y1);
} else if (skipBottomLeft) { } else if (skipBottomLeft) {
cr.lineTo(x1 - rise, y2); cr.lineTo(x1 - rise, y2)
cr.lineTo(x1 - rise, y2 - halfBase); cr.lineTo(x1 - rise, y2 - halfBase);
} else { } else {
cr.lineTo(x1, this._arrowOrigin + halfBase); cr.lineTo(x1, this._arrowOrigin + halfBase);
@@ -402,7 +442,7 @@ var BoxPointer = GObject.registerClass({
if (!skipTopLeft) { if (!skipTopLeft) {
cr.lineTo(x1, y1 + borderRadius); cr.lineTo(x1, y1 + borderRadius);
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius, cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
Math.PI, 3 * Math.PI / 2); Math.PI, 3*Math.PI/2);
} }
Clutter.cairo_set_source_color(cr, backgroundColor); Clutter.cairo_set_source_color(cr, backgroundColor);
@@ -419,25 +459,15 @@ var BoxPointer = GObject.registerClass({
} }
setPosition(sourceActor, alignment) { setPosition(sourceActor, alignment) {
if (!this._sourceActor || sourceActor != this._sourceActor) { // We need to show it now to force an allocation,
if (this._sourceActorDestroyId) { // so that we can query the correct size.
this._sourceActor.disconnect(this._sourceActorDestroyId); this.show();
delete this._sourceActorDestroyId;
}
this._sourceActor = sourceActor; this._sourceActor = sourceActor;
if (this._sourceActor) {
this._sourceActorDestroyId = this._sourceActor.connect('destroy', () => {
this._sourceActor = null;
delete this._sourceActorDestroyId;
});
}
}
this._arrowAlignment = alignment; this._arrowAlignment = alignment;
this.queue_relayout(); this._reposition();
this._updateFlip();
} }
setSourceAlignment(alignment) { setSourceAlignment(alignment) {
@@ -449,31 +479,27 @@ var BoxPointer = GObject.registerClass({
this.setPosition(this._sourceActor, this._arrowAlignment); this.setPosition(this._sourceActor, this._arrowAlignment);
} }
_reposition(allocationBox) { _reposition() {
let sourceActor = this._sourceActor; let sourceActor = this._sourceActor;
let alignment = this._arrowAlignment; 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 // Position correctly relative to the sourceActor
let sourceNode = sourceActor.get_theme_node(); let sourceNode = sourceActor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box()); let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
let sourceAllocation = this._sourceAllocation; let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment; 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 sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [, , natWidth, natHeight] = this.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
// We also want to keep it onscreen, and separated from the // We also want to keep it onscreen, and separated from the
// edge by the same distance as the main part of the box is // edge by the same distance as the main part of the box is
// separated from its sourceActor // separated from its sourceActor
let workarea = this._workArea; let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width'); let borderWidth = themeNode.get_length('-arrow-border-width');
let arrowBase = themeNode.get_length('-arrow-base'); let arrowBase = themeNode.get_length('-arrow-base');
let borderRadius = themeNode.get_length('-arrow-border-radius'); let borderRadius = themeNode.get_length('-arrow-border-radius');
let margin = 4 * borderRadius + borderWidth + arrowBase; let margin = (4 * borderRadius + borderWidth + arrowBase);
let gap = themeNode.get_length('-boxpointer-gap'); let gap = themeNode.get_length('-boxpointer-gap');
let padding = themeNode.get_length('-arrow-rise'); let padding = themeNode.get_length('-arrow-rise');
@@ -507,7 +533,7 @@ var BoxPointer = GObject.registerClass({
// of the box to maintain the arrow's accuracy. // of the box to maintain the arrow's accuracy.
let arrowOrigin; let arrowOrigin;
let halfBase = Math.floor(arrowBase / 2); let halfBase = Math.floor(arrowBase/2);
let halfBorder = borderWidth / 2; let halfBorder = borderWidth / 2;
let halfMargin = margin / 2; let halfMargin = margin / 2;
let [x1, y1] = [halfBorder, halfBorder]; let [x1, y1] = [halfBorder, halfBorder];
@@ -518,17 +544,17 @@ var BoxPointer = GObject.registerClass({
case St.Side.BOTTOM: case St.Side.BOTTOM:
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment); resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
resX = Math.max(resX, workarea.x + padding); resX = Math.max(resX, monitor.x + padding);
resX = Math.min(resX, workarea.x + workarea.width - (padding + natWidth)); resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
arrowOrigin = sourceCenterX - resX; arrowOrigin = sourceCenterX - resX;
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) { if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
if (arrowOrigin > x1) if (arrowOrigin > x1)
resX += arrowOrigin - x1; resX += (arrowOrigin - x1);
arrowOrigin = x1; arrowOrigin = x1;
} else if (arrowOrigin >= (x2 - (borderRadius + halfBase))) { } else if (arrowOrigin >= (x2 - (borderRadius + halfBase))) {
if (arrowOrigin < x2) if (arrowOrigin < x2)
resX -= x2 - arrowOrigin; resX -= (x2 - arrowOrigin);
arrowOrigin = x2; arrowOrigin = x2;
} }
break; break;
@@ -537,17 +563,17 @@ var BoxPointer = GObject.registerClass({
case St.Side.RIGHT: case St.Side.RIGHT:
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment); resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
resY = Math.max(resY, workarea.y + padding); resY = Math.max(resY, monitor.y + padding);
resY = Math.min(resY, workarea.y + workarea.height - (padding + natHeight)); resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
arrowOrigin = sourceCenterY - resY; arrowOrigin = sourceCenterY - resY;
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) { if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
if (arrowOrigin > y1) if (arrowOrigin > y1)
resY += arrowOrigin - y1; resY += (arrowOrigin - y1);
arrowOrigin = y1; arrowOrigin = y1;
} else if (arrowOrigin >= (y2 - (borderRadius + halfBase))) { } else if (arrowOrigin >= (y2 - (borderRadius + halfBase))) {
if (arrowOrigin < y2) if (arrowOrigin < y2)
resX -= y2 - arrowOrigin; resX -= (y2 - arrowOrigin);
arrowOrigin = y2; arrowOrigin = y2;
} }
break; break;
@@ -562,8 +588,9 @@ var BoxPointer = GObject.registerClass({
parent = parent.get_parent(); parent = parent.get_parent();
} }
// Actually set the position this._xPosition = Math.floor(x);
allocationBox.set_origin(Math.floor(x), Math.floor(y)); this._yPosition = Math.floor(y);
this._shiftActor();
} }
// @origin: Coordinate specifying middle of the arrow, along // @origin: Coordinate specifying middle of the arrow, along
@@ -586,30 +613,44 @@ 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) { _calculateArrowSide(arrowSide) {
let sourceAllocation = this._sourceAllocation; let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let [, , boxWidth, boxHeight] = this.get_preferred_size(); let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let workarea = this._workArea; let monitorActor = this.sourceActor;
if (!monitorActor)
monitorActor = this;
let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
switch (arrowSide) { switch (arrowSide) {
case St.Side.TOP: case St.Side.TOP:
if (sourceAllocation.y2 + boxHeight > workarea.y + workarea.height && if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
boxHeight < sourceAllocation.y1 - workarea.y) boxHeight < sourceAllocation.y1 - monitor.y)
return St.Side.BOTTOM; return St.Side.BOTTOM;
break; break;
case St.Side.BOTTOM: case St.Side.BOTTOM:
if (sourceAllocation.y1 - boxHeight < workarea.y && if (sourceAllocation.y1 - boxHeight < monitor.y &&
boxHeight < workarea.y + workarea.height - sourceAllocation.y2) boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
return St.Side.TOP; return St.Side.TOP;
break; break;
case St.Side.LEFT: case St.Side.LEFT:
if (sourceAllocation.x2 + boxWidth > workarea.x + workarea.width && if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - workarea.x) boxWidth < sourceAllocation.x1 - monitor.x)
return St.Side.RIGHT; return St.Side.RIGHT;
break; break;
case St.Side.RIGHT: case St.Side.RIGHT:
if (sourceAllocation.x1 - boxWidth < workarea.x && if (sourceAllocation.x1 - boxWidth < monitor.x &&
boxWidth < workarea.x + workarea.width - sourceAllocation.x2) boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return St.Side.LEFT; return St.Side.LEFT;
break; break;
} }
@@ -617,16 +658,38 @@ var BoxPointer = GObject.registerClass({
return arrowSide; return arrowSide;
} }
_updateFlip(allocationBox) { _updateFlip() {
let arrowSide = this._calculateArrowSide(this._userArrowSide); let arrowSide = this._calculateArrowSide(this._userArrowSide);
if (this._arrowSide != arrowSide) { if (this._arrowSide != arrowSide) {
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
this._reposition(allocationBox); this._reposition();
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.queue_relayout();
return false;
});
this.emit('arrow-side-changed'); this.emit('arrow-side-changed');
} }
} }
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) { updateArrowSide(side) {
this._arrowSide = side; this._arrowSide = side;
this._border.queue_repaint(); this._border.queue_repaint();

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