Compare commits

..

1 Commits

Author SHA1 Message Date
Florian Müllner
078a1bda14 shellDBus: Return error on invalid app IDs
When passing an invalid or unknown app ID to FocusApp(), we currently
open the app picker and silently fail to select the desired app.
Instead of half-working like that, make it clear that the argument
was invalid by returning an appropriate error. (It's easy to get the
ID wrong, as unlike appstream/flatpak IDs, we include the ".desktop"
suffix).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/337
2019-01-08 22:40:56 +01:00
322 changed files with 36974 additions and 57291 deletions

1
.gitignore vendored
View File

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

View File

@@ -1,88 +0,0 @@
stages:
- review
- source_check
- build
- test
variables:
JS_LOG: "js-report.txt"
POT_LOG: "pot-update.txt"
.only_default: &only_default
only:
- branches
- tags
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
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: source_check
script:
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG)
<<: *only_default
only:
changes:
- js/**/*
artifacts:
paths:
- ${JS_LOG}
when: on_failure
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: build
before_script:
- .gitlab-ci/checkout-mutter.sh
- meson mutter mutter/build --prefix=/usr -Dtests=false
- ninja -C mutter/build install
script:
- meson . build -Dbuiltype=debugoptimized
- ninja -C build
- ninja -C build install
<<: *only_default
artifacts:
expire_in: 1 day
paths:
- mutter
- build
test:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: test
before_script:
- ninja -C mutter/build install
script:
- xvfb-run meson test -C build --no-rebuild
<<: *only_default
artifacts:
expire_in: 1 day
paths:
- build/meson-logs/testlog.txt
when: on_failure
test-pot:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
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)' && \
# 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,35 +0,0 @@
#!/usr/bin/bash
shell_branch=$(git describe --contains --all HEAD)
mutter_target=
git clone https://gitlab.gnome.org/GNOME/mutter.git
if [ $? -ne 0 ]; then
echo Checkout failed
exit 1
fi
cd mutter
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//gnome-shell/mutter}
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
echo Looking for $merge_request_branch on remote ...
if git fetch -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/$shell_branch)
mutter_target=${mutter_target:-$(git branch -r -l ${shell_branch#remotes/})}
mutter_target=${mutter_target:-origin/master}
echo Using $mutter_target instead
fi
git checkout -q $mutter_target

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,7 +80,10 @@ 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 Lang = imports.lang;
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;
@@ -118,53 +121,60 @@ See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/N
## Classes ## Classes
There are many approaches to classes in JavaScript. We use standard ES6 classes There are many approaches to classes in JavaScript. We use our own class framework
whenever possible, that is when not inheriting from GObjects. (sigh), which is built in gjs. The advantage is that it supports inheriting from
GObjects, although this feature isn't used very often in the Shell itself.
```javascript ```javascript
var IconLabelMenuItem = class extends PopupMenu.PopupMenuBaseItem { var IconLabelMenuItem = new Lang.Class({
constructor(icon, label) { Name: 'IconLabelMenuItem',
super({ reactive: false }); Extends: PopupMenu.PopupMenuBaseItem,
_init(icon, label) {
this.parent({ reactive: false });
this.actor.add_child(icon); this.actor.add_child(icon);
this.actor.add_child(label); this.actor.add_child(label);
} },
open() { open() {
log("menu opened!"); log("menu opened!");
} }
};
```
For GObject inheritence, we use the GObject.registerClass() function provided
by gjs.
```javascript
var MyActor = GObject.registerClass(
class MyActor extends Clutter.Actor {
_init(params) {
super._init(params);
this.name = 'MyCustomActor';
}
}); });
``` ```
* 'Name' is required. 'Extends' is optional. If you leave it out, you will
automatically inherit from Object.
* Leave a blank line between the "class header" (Name, Extends, and other
things) and the "class body" (methods). Leave a blank line between each
method.
* No space before the colon, one space after.
* No trailing comma after the last item.
* Make sure to use a semicolon after the closing paren to the class. It's
still a giant function call, even though it may resemble a more
conventional syntax.
## GObject Introspection ## GObject Introspection
GObject Introspection is a powerful feature that allows us to have native GObject Introspection is a powerful feature that allows us to have native
bindings for almost any library built around GObject. If a library requires bindings for almost any library built around GObject. If a library requires
you to inherit from a type to use it, you can do so: you to inherit from a type to use it, you can do so:
```javascript ```javascript
var MyClutterActor = GObject.registerClass( var MyClutterActor = new Lang.Class({
class MyClutterActor extends Clutter.Actor { Name: '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() { vfunc_paint(actor) {
let alloc = this.get_allocation_box(); let alloc = this.get_allocation_box();
Cogl.set_source_color4ub(255, 0, 0, 255); Cogl.set_source_color4ub(255, 0, 0, 255);
Cogl.rectangle(alloc.x1, alloc.y1, Cogl.rectangle(alloc.x1, alloc.y1,
@@ -197,18 +207,20 @@ that has a property called `actor`. We call this 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 ```javascript
var MyClass = class { var MyClass = new Lang.Class({
constructor() { Name: 'MyClass',
_init() {
this.actor = new St.Button({ text: "This is a button" }); this.actor = new St.Button({ text: "This is a button" });
this.actor._delegate = this; this.actor._delegate = this;
this.actor.connect('clicked', this._onClicked.bind(this)); this.actor.connect('clicked', this._onClicked.bind(this));
} },
_onClicked(actor) { _onClicked(actor) {
actor.set_label("You clicked the button!"); actor.set_label("You clicked the button!");
} }
}; });
``` ```
The 'delegate' property is important for anything which trying to get the The 'delegate' property is important for anything which trying to get the
@@ -234,6 +246,8 @@ variable that can be captured in closures.
All closures should be wrapped with Function.prototype.bind or use arrow All closures should be wrapped with Function.prototype.bind or use arrow
notation. notation.
```javascript ```javascript
const Lang = imports.lang;
let closure1 = () => { this._fnorbate(); }; let closure1 = () => { this._fnorbate(); };
let closure2 = this._fnorbate.bind(this); let closure2 = this._fnorbate.bind(this);
``` ```
@@ -241,18 +255,19 @@ notation.
A more realistic example would be connecting to a signal on a method of a A more realistic example would be connecting to a signal on a method of a
prototype: prototype:
```javascript ```javascript
const Lang = imports.lang;
const FnorbLib = imports.fborbLib; const FnorbLib = imports.fborbLib;
var MyClass = class { var MyClass = new Lang.Class({
_init() { _init() {
let fnorb = new FnorbLib.Fnorb(); let fnorb = new FnorbLib.Fnorb();
fnorb.connect('frobate', this._onFnorbFrobate.bind(this)); fnorb.connect('frobate', this._onFnorbFrobate.bind(this));
} },
_onFnorbFrobate(fnorb) { _onFnorbFrobate(fnorb) {
this._updateFnorb(); this._updateFnorb();
} }
}; });
``` ```
## Object literal syntax ## Object literal syntax
@@ -286,21 +301,23 @@ property.
```javascript ```javascript
var ANIMATION_TIME = 2000; var ANIMATION_TIME = 2000;
var MyClass = class { var MyClass = new Lang.Class({
constructor() { Name: 'MyClass',
_init() {
this.actor = new St.BoxLayout(); this.actor = new St.BoxLayout();
this._position = 0; this._position = 0;
} },
get position() { get position() {
return this._position; return this._position;
} },
set position(value) { set position(value) {
this._position = value; this._position = value;
this.actor.set_position(value, value); this.actor.set_position(value, value);
} }
}; });
let myThing = new MyClass(); let myThing = new MyClass();
Tweener.addTween(myThing, Tweener.addTween(myThing,

220
NEWS
View File

@@ -1,223 +1,3 @@
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
======
* Improve icon grid performance [Daniel; #174]
* Remove browser plugin [Michael; #766776]
* Add DBus API for introspecting the application state [Jonas, Olivier; !326]
* Always allow leaving the overview via the hot-corner [Pascal; #429]
* Misc. bug fixes [Florian, Jasper, Andrea, Sam, Dani, Cosimo, Jonas, Carlos;
#643595, #673767, !293, #783, #781, !298, !297, #782, !301, !314, !305, #799,
#632, !327]
Contributors:
Jonas Ådahl, Andrea Azzarone, Michael Catanzaro, Cosimo Cecchi, daniruiz,
Olivier Fourdan, Carlos Garnacho, Sam Hewitt, Andre Klapper, Florian Müllner,
Pascal Nowack, Jasper St. Pierre, RyuzakiKK, Marco Trevisan (Treviño),
João Paulo Rechi Vita, Daniel van Vugt
Translators:
Kristjan SCHMIDT [eo], Matej Urbančič [sl], Daniel Mustieles [es],
Fabio Tomat [fur], Emin Tufan Çetin [tr], Anders Jonsson [sv],
Ryuta Fujii [ja]
3.31.2 3.31.2
====== ======
* Port away from and remove ShellGenericContainer [Georges; !153] * Port away from and remove ShellGenericContainer [Georges; !153]

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,6 +1,5 @@
dbus_interfaces = [ dbus_interfaces = [
'org.gnome.Shell.Extensions.xml', 'org.gnome.Shell.Extensions.xml',
'org.gnome.Shell.Introspect.xml',
'org.gnome.Shell.PadOsd.xml', 'org.gnome.Shell.PadOsd.xml',
'org.gnome.Shell.Screencast.xml', 'org.gnome.Shell.Screencast.xml',
'org.gnome.Shell.Screenshot.xml', 'org.gnome.Shell.Screenshot.xml',

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,61 +0,0 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Shell.Introspect:
@short_description: Introspection interface
The interface used to introspect the state of Shell, such as running
applications, currently active application, etc.
-->
<interface name="org.gnome.Shell.Introspect">
<!--
RunningApplicationsChanged:
@short_description: Notifies when the running applications changes
-->
<signal name="RunningApplicationsChanged" />
<!--
GetRunningApplications:
@short_description: Retrieves the description of all running applications
Each application is associated by an application ID. The details of
each application consists of a varlist of keys and values. Available
keys are listed below.
'active-on-seats' - (as) list of seats the application is active on
(a seat only has at most one active
application)
-->
<method name="GetRunningApplications">
<arg name="apps" direction="out" type="a{sa{sv}}" />
</method>
<!--
GetWindows:
@short_description: Retrieves the current list of windows and their properties
A window is exposed as:
* t ID: unique ID of the window
* a{sv} properties: high-level properties
Known properties:
- "title" (s): (readonly) title of the window
- "app-id" (s): (readonly) application ID of the window
- "wm-class" (s): (readonly) class of the window
- "client-type" (u): (readonly) 0 for Wayland, 1 for X11
- "is-hidden" (b): (readonly) if the window is currently hidden
- "has-focus" (b): (readonly) if the window currently have
keyboard focus
- "width" (u): (readonly) width of the window
- "height" (u): (readonly) height of the window
-->
<method name="GetWindows">
<arg name="windows" direction="out" type="a{ta{sv}}" />
</method>
</interface>
</node>

View File

@@ -9,6 +9,9 @@
<method name="ShowOSD"> <method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/> <arg type="a{sv}" direction="in" name="params"/>
</method> </method>
<method name="ShowMonitorLabels">
<arg type="a{uv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels2"> <method name="ShowMonitorLabels2">
<arg type="a{sv}" direction="in" name="params"/> <arg type="a{sv}" direction="in" name="params"/>
</method> </method>
@@ -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,9 +39,7 @@
<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.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.HotplugSniffer.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.HotplugSniffer.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.PerfHelper.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.PerfHelper.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.PortalHelper.xml</file> <file preprocess="xml-stripblanks">org.gnome.Shell.PortalHelper.xml</file>

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

@@ -90,15 +90,8 @@
adapter is ever seen not to have devices associated to it. adapter is ever seen not to have devices associated to it.
</description> </description>
</key> </key>
<key name="introspect" type="b">
<default>false</default>
<summary>Enable introspection API</summary>
<description>
Enables a D-Bus API that allows to introspect the application state of
the shell.
</description>
</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/"
@@ -144,41 +137,16 @@
<summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary> <summary>Keybinding that pauses and resumes all running tweens, for debugging purposes</summary>
<description></description> <description></description>
</key> </key>
<key name="switch-to-application-1" type="as"> </schema>
<default>["&lt;Super&gt;1"]</default>
<summary>Switch to application 1</summary> <schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
</key> gettext-domain="@GETTEXT_PACKAGE@">
<key name="switch-to-application-2" type="as"> <key name="keyboard-type" type="s">
<default>["&lt;Super&gt;2"]</default> <default>'touch'</default>
<summary>Switch to application 2</summary> <summary>Which keyboard to use</summary>
</key> <description>
<key name="switch-to-application-3" type="as"> The type of keyboard to use.
<default>["&lt;Super&gt;3"]</default> </description>
<summary>Switch to application 3</summary>
</key>
<key name="switch-to-application-4" type="as">
<default>["&lt;Super&gt;4"]</default>
<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>

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

@@ -1,5 +1,12 @@
const Lang = imports.lang;
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;
@@ -17,8 +24,9 @@ function stripPrefix(string, prefix) {
return string; return string;
} }
var Application = class { var Application = new Lang.Class({
constructor() { Name: 'Application',
_init() {
GLib.set_prgname('gnome-shell-extension-prefs'); GLib.set_prgname('gnome-shell-extension-prefs');
this.application = new Gtk.Application({ this.application = new Gtk.Application({
application_id: 'org.gnome.shell.ExtensionPrefs', application_id: 'org.gnome.shell.ExtensionPrefs',
@@ -34,7 +42,7 @@ var Application = class {
this._startupUuid = null; this._startupUuid = null;
this._loaded = false; this._loaded = false;
this._skipMainWindow = false; this._skipMainWindow = false;
} },
_extensionAvailable(uuid) { _extensionAvailable(uuid) {
let extension = ExtensionUtils.extensions[uuid]; let extension = ExtensionUtils.extensions[uuid];
@@ -46,7 +54,7 @@ var Application = class {
return false; return false;
return true; return true;
} },
_getExtensionPrefsModule(extension) { _getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid; let uuid = extension.metadata.uuid;
@@ -61,7 +69,7 @@ var Application = class {
this._extensionPrefsModules[uuid] = prefsModule; this._extensionPrefsModules[uuid] = prefsModule;
return prefsModule; return prefsModule;
} },
_selectExtension(uuid) { _selectExtension(uuid) {
if (!this._extensionAvailable(uuid)) if (!this._extensionAvailable(uuid))
@@ -96,122 +104,33 @@ var Application = class {
dialog.set_default_size(600, 400); dialog.set_default_size(600, 400);
dialog.add(widget); dialog.add(widget);
dialog.show(); dialog.show();
} },
_buildErrorUI(extension, 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: 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 ${extension.uuid} had an error:`,
'```',
`${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: extension.metadata.url != null
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(extension.metadata.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(app) { _buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: app, this._window = new Gtk.ApplicationWindow({ application: app,
@@ -231,12 +150,8 @@ var Application = class {
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));
@@ -244,8 +159,6 @@ var Application = class {
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('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => { this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
@@ -254,13 +167,13 @@ var Application = class {
}); });
this._window.show_all(); this._window.show_all();
} },
_sortList(row1, row2) { _sortList(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name; let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name; let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2); return name1.localeCompare(name2);
} },
_updateHeader(row, before) { _updateHeader(row, before) {
if (!before || row.get_header()) if (!before || row.get_header())
@@ -268,14 +181,14 @@ var Application = class {
let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL }); let sep = new Gtk.Separator({ orientation: Gtk.Orientation.HORIZONTAL });
row.set_header(sep); row.set_header(sep);
} },
_scanExtensions() { _scanExtensions() {
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', this._extensionFound.bind(this)); finder.connect('extension-found', this._extensionFound.bind(this));
finder.scanExtensions(); finder.scanExtensions();
this._extensionsLoaded(); this._extensionsLoaded();
} },
_extensionFound(finder, extension) { _extensionFound(finder, extension) {
let row = new ExtensionRow(extension.uuid); let row = new ExtensionRow(extension.uuid);
@@ -287,29 +200,24 @@ var Application = class {
row.show_all(); row.show_all();
this._extensionSelector.add(row); this._extensionSelector.add(row);
} },
_extensionsLoaded() { _extensionsLoaded() {
if (this._extensionSelector.get_children().length > 0)
this._mainStack.visible_child_name = 'listing';
else
this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid && this._extensionAvailable(this._startupUuid)) if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid); this._selectExtension(this._startupUuid);
this._startupUuid = null; this._startupUuid = null;
this._skipMainWindow = false; this._skipMainWindow = false;
this._loaded = true; this._loaded = true;
} },
_onActivate() { _onActivate() {
this._window.present(); this._window.present();
} },
_onStartup(app) { _onStartup(app) {
this._buildUI(app); this._buildUI(app);
this._scanExtensions(); this._scanExtensions();
} },
_onCommandLine(app, commandLine) { _onCommandLine(app, commandLine) {
app.activate(); app.activate();
@@ -332,187 +240,26 @@ var Application = class {
} }
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( var DescriptionLabel = new Lang.Class({
class EmptyPlaceholder extends Gtk.Box { Name: 'DescriptionLabel',
_init() { Extends: Gtk.Label,
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 DescriptionLabel = GObject.registerClass(
class DescriptionLabel extends Gtk.Label {
vfunc_get_preferred_height_for_width(width) { vfunc_get_preferred_height_for_width(width) {
// Hack: Request the maximum height allowed by the line limit // Hack: Request the maximum height allowed by the line limit
if (this.lines > 0) if (this.lines > 0)
return super.vfunc_get_preferred_height_for_width(0); return this.parent(0);
return super.vfunc_get_preferred_height_for_width(width); return this.parent(width);
} }
}); });
var ExtensionRow = GObject.registerClass( var ExtensionRow = new Lang.Class({
class ExtensionRow extends Gtk.ListBoxRow { Name: 'ExtensionRow',
Extends: Gtk.ListBoxRow,
_init(uuid) { _init(uuid) {
super._init(); this.parent();
this.uuid = uuid; this.uuid = uuid;
@@ -530,7 +277,7 @@ class ExtensionRow extends Gtk.ListBoxRow {
}); });
this._buildUI(); this._buildUI();
} },
_buildUI() { _buildUI() {
let extension = ExtensionUtils.extensions[this.uuid]; let extension = ExtensionUtils.extensions[this.uuid];
@@ -558,7 +305,7 @@ class ExtensionRow extends Gtk.ListBoxRow {
let button = new Gtk.Button({ valign: Gtk.Align.CENTER, let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
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');
@@ -577,7 +324,7 @@ class ExtensionRow extends Gtk.ListBoxRow {
}); });
this._switch.connect('state-set', () => true); this._switch.connect('state-set', () => true);
hbox.add(this._switch); hbox.add(this._switch);
} },
_canEnable() { _canEnable() {
let extension = ExtensionUtils.extensions[this.uuid]; let extension = ExtensionUtils.extensions[this.uuid];
@@ -585,21 +332,21 @@ class ExtensionRow extends Gtk.ListBoxRow {
return !this._settings.get_boolean('disable-user-extensions') && return !this._settings.get_boolean('disable-user-extensions') &&
!(checkVersion && ExtensionUtils.isOutOfDate(extension)); !(checkVersion && ExtensionUtils.isOutOfDate(extension));
} },
_isEnabled() { _isEnabled() {
let extensions = this._settings.get_strv('enabled-extensions'); let extensions = this._settings.get_strv('enabled-extensions');
return extensions.includes(this.uuid); return extensions.indexOf(this.uuid) != -1;
} },
_enable() { _enable() {
let extensions = this._settings.get_strv('enabled-extensions'); let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.includes(this.uuid)) if (extensions.indexOf(this.uuid) != -1)
return; return;
extensions.push(this.uuid); extensions.push(this.uuid);
this._settings.set_strv('enabled-extensions', extensions); this._settings.set_strv('enabled-extensions', extensions);
} },
_disable() { _disable() {
let extensions = this._settings.get_strv('enabled-extensions'); let extensions = this._settings.get_strv('enabled-extensions');
@@ -618,12 +365,12 @@ 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'])

View File

@@ -1,7 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Pango, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Signals = imports.signals; 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;
@@ -34,8 +38,10 @@ var BeginRequestType = {
DONT_PROVIDE_USERNAME: 1 DONT_PROVIDE_USERNAME: 1
}; };
var AuthPrompt = class { var AuthPrompt = new Lang.Class({
constructor(gdmClient, mode) { Name: 'AuthPrompt',
_init(gdmClient, mode) {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient; this._gdmClient = gdmClient;
@@ -93,7 +99,7 @@ var AuthPrompt = class {
x_align: St.Align.START }); x_align: St.Align.START });
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry', this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true }); can_focus: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE }); ShellEntry.addContextMenu(this._entry, { isPassword: true });
this.actor.add(this._entry, this.actor.add(this._entry,
{ expand: true, { expand: true,
@@ -121,16 +127,17 @@ var AuthPrompt = class {
this._initButtons(); this._initButtons();
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE); let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._spinner = new Animation.AnimatedIcon(spinnerIcon, DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0; this._spinner.actor.opacity = 0;
this._spinner.actor.show(); this._spinner.actor.show();
this._defaultButtonWell.add_child(this._spinner.actor); this._defaultButtonWell.add_child(this._spinner.actor);
} },
_onDestroy() { _onDestroy() {
this._userVerifier.destroy(); this._userVerifier.destroy();
this._userVerifier = null; this._userVerifier = null;
} },
_initButtons() { _initButtons() {
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button', this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
@@ -138,7 +145,7 @@ var AuthPrompt = class {
reactive: true, reactive: true,
can_focus: true, can_focus: true,
label: _("Cancel") }); label: _("Cancel") });
this.cancelButton.connect('clicked', () => this.cancel()); this.cancelButton.connect('clicked', () => { this.cancel(); });
this._buttonBox.add(this.cancelButton, this._buttonBox.add(this.cancelButton,
{ expand: false, { expand: false,
x_fill: false, x_fill: false,
@@ -157,7 +164,7 @@ var AuthPrompt = class {
reactive: true, reactive: true,
can_focus: true, can_focus: true,
label: _("Next") }); label: _("Next") });
this.nextButton.connect('clicked', () => this.emit('next')); this.nextButton.connect('clicked', () => { this.emit('next'); });
this.nextButton.add_style_pseudo_class('default'); this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add(this.nextButton, this._buttonBox.add(this.nextButton,
{ expand: false, { expand: false,
@@ -178,7 +185,7 @@ var AuthPrompt = class {
if (this.nextButton.reactive) if (this.nextButton.reactive)
this.emit('next'); this.emit('next');
}); });
} },
_onAskQuestion(verifier, serviceName, question, passwordChar) { _onAskQuestion(verifier, serviceName, question, passwordChar) {
if (this._queryingService) if (this._queryingService)
@@ -204,12 +211,12 @@ var AuthPrompt = class {
this.updateSensitivity(true); this.updateSensitivity(true);
this.emit('prompted'); this.emit('prompted');
} },
_onOVirtUserAuthenticated() { _onOVirtUserAuthenticated() {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset(); this.reset();
} },
_onSmartcardStatusChanged() { _onSmartcardStatusChanged() {
this.smartcardDetected = this._userVerifier.smartcardDetected; this.smartcardDetected = this._userVerifier.smartcardDetected;
@@ -228,12 +235,12 @@ var AuthPrompt = class {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset(); this.reset();
} },
_onShowMessage(userVerifier, message, type) { _onShowMessage(userVerifier, message, type) {
this.setMessage(message, type); this.setMessage(message, type);
this.emit('prompted'); this.emit('prompted');
} },
_onVerificationFailed(userVerifier, canRetry) { _onVerificationFailed(userVerifier, canRetry) {
this._queryingService = null; this._queryingService = null;
@@ -242,22 +249,22 @@ var AuthPrompt = class {
this.updateSensitivity(canRetry); this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
} },
_onVerificationComplete() { _onVerificationComplete() {
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED; this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false; this.cancelButton.reactive = false;
} },
_onReset() { _onReset() {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.reset(); this.reset();
} },
addActorToDefaultButtonWell(actor) { addActorToDefaultButtonWell(actor) {
this._defaultButtonWell.add_child(actor); this._defaultButtonWell.add_child(actor);
} },
setActorInDefaultButtonWell(actor, animate) { setActorInDefaultButtonWell(actor, animate) {
if (!this._defaultButtonWellActor && if (!this._defaultButtonWellActor &&
@@ -295,7 +302,8 @@ var AuthPrompt = class {
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME, time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear', transition: 'linear',
onComplete: () => { onCompleteScope: this,
onComplete() {
if (wasSpinner) { if (wasSpinner) {
if (this._spinner) if (this._spinner)
this._spinner.stop(); this._spinner.stop();
@@ -320,25 +328,25 @@ var AuthPrompt = class {
} }
this._defaultButtonWellActor = actor; this._defaultButtonWellActor = actor;
} },
startSpinning() { startSpinning() {
this.setActorInDefaultButtonWell(this._spinner.actor, true); this.setActorInDefaultButtonWell(this._spinner.actor, true);
} },
stopSpinning() { stopSpinning() {
this.setActorInDefaultButtonWell(null, false); this.setActorInDefaultButtonWell(null, false);
} },
clear() { clear() {
this._entry.text = ''; this._entry.text = '';
this.stopSpinning(); this.stopSpinning();
} },
setPasswordChar(passwordChar) { setPasswordChar(passwordChar) {
this._entry.clutter_text.set_password_char(passwordChar); this._entry.clutter_text.set_password_char(passwordChar);
this._entry.menu.isPassword = passwordChar != ''; this._entry.menu.isPassword = passwordChar != '';
} },
setQuestion(question) { setQuestion(question) {
this._label.set_text(question); this._label.set_text(question);
@@ -347,7 +355,7 @@ var AuthPrompt = class {
this._entry.show(); this._entry.show();
this._entry.grab_key_focus(); this._entry.grab_key_focus();
} },
getAnswer() { getAnswer() {
let text; let text;
@@ -360,7 +368,7 @@ var AuthPrompt = class {
} }
return text; return text;
} },
_fadeOutMessage() { _fadeOutMessage() {
if (this._message.opacity == 0) if (this._message.opacity == 0)
@@ -371,7 +379,7 @@ var AuthPrompt = class {
time: MESSAGE_FADE_OUT_ANIMATION_TIME, time: MESSAGE_FADE_OUT_ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
} },
setMessage(message, type) { setMessage(message, type) {
if (type == GdmUtil.MessageType.ERROR) if (type == GdmUtil.MessageType.ERROR)
@@ -391,18 +399,18 @@ var AuthPrompt = class {
} else { } else {
this._message.opacity = 0; this._message.opacity = 0;
} }
} },
_updateNextButtonSensitivity(sensitive) { _updateNextButtonSensitivity(sensitive) {
this.nextButton.reactive = sensitive; this.nextButton.reactive = sensitive;
this.nextButton.can_focus = sensitive; this.nextButton.can_focus = sensitive;
} },
updateSensitivity(sensitive) { updateSensitivity(sensitive) {
this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING)); this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
this._entry.reactive = sensitive; this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive; this._entry.clutter_text.editable = sensitive;
} },
hide() { hide() {
this.setActorInDefaultButtonWell(null, true); this.setActorInDefaultButtonWell(null, true);
@@ -413,7 +421,7 @@ var AuthPrompt = class {
this.updateSensitivity(true); this.updateSensitivity(true);
this._entry.set_text(''); this._entry.set_text('');
} },
setUser(user) { setUser(user) {
let oldChild = this._userWell.get_child(); let oldChild = this._userWell.get_child();
@@ -424,7 +432,7 @@ var AuthPrompt = class {
let userWidget = new UserWidget.UserWidget(user); let userWidget = new UserWidget.UserWidget(user);
this._userWell.set_child(userWidget.actor); this._userWell.set_child(userWidget.actor);
} }
} },
reset() { reset() {
let oldStatus = this.verificationStatus; let oldStatus = this.verificationStatus;
@@ -462,7 +470,7 @@ var AuthPrompt = class {
} }
this.emit('reset', beginRequestType); this.emit('reset', beginRequestType);
} },
addCharacter(unichar) { addCharacter(unichar) {
if (!this._entry.visible) if (!this._entry.visible)
@@ -470,7 +478,7 @@ var AuthPrompt = class {
this._entry.grab_key_focus(); this._entry.grab_key_focus();
this._entry.clutter_text.insert_unichar(unichar); this._entry.clutter_text.insert_unichar(unichar);
} },
begin(params) { begin(params) {
params = Params.parse(params, { userName: null, params = Params.parse(params, { userName: null,
@@ -484,7 +492,7 @@ var AuthPrompt = class {
this._userVerifier.begin(params.userName, hold); this._userVerifier.begin(params.userName, hold);
this.verificationStatus = AuthPromptStatus.VERIFYING; this.verificationStatus = AuthPromptStatus.VERIFYING;
} },
finish(onComplete) { finish(onComplete) {
if (!this._userVerifier.hasPendingMessages) { if (!this._userVerifier.hasPendingMessages) {
@@ -498,7 +506,7 @@ var AuthPrompt = class {
this._userVerifier.clear(); this._userVerifier.clear();
onComplete(); onComplete();
}); });
} },
cancel() { cancel() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) { if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
@@ -507,5 +515,5 @@ var AuthPrompt = class {
this.reset(); this.reset();
this.emit('cancelled'); this.emit('cancelled');
} }
}; });
Signals.addSignalMethods(AuthPrompt.prototype); Signals.addSignalMethods(AuthPrompt.prototype);

View File

@@ -44,40 +44,45 @@
* replaced by something else. * replaced by something else.
*/ */
const { GObject } = imports.gi; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
var Task = class { var Task = new Lang.Class({
constructor(scope, handler) { Name: 'Task',
_init(scope, handler) {
if (scope) if (scope)
this.scope = scope; this.scope = scope;
else else
this.scope = this; this.scope = this;
this.handler = handler; this.handler = handler;
} },
run() { run() {
if (this.handler) if (this.handler)
return this.handler.call(this.scope); return this.handler.call(this.scope);
return null; return null;
} },
}; });
Signals.addSignalMethods(Task.prototype); Signals.addSignalMethods(Task.prototype);
var Hold = class extends Task { var Hold = new Lang.Class({
constructor() { Name: 'Hold',
super(null, () => this); Extends: Task,
_init() {
this.parent(this, () => this);
this._acquisitions = 1; this._acquisitions = 1;
} },
acquire() { acquire() {
if (this._acquisitions <= 0) if (this._acquisitions <= 0)
throw new Error("Cannot acquire hold after it's been released"); throw new Error("Cannot acquire hold after it's been released");
this._acquisitions++; this._acquisitions++;
} },
acquireUntilAfter(hold) { acquireUntilAfter(hold) {
if (!hold.isAcquired()) if (!hold.isAcquired())
@@ -88,24 +93,27 @@ var Hold = class extends Task {
hold.disconnect(signalId); hold.disconnect(signalId);
this.release(); this.release();
}); });
} },
release() { release() {
this._acquisitions--; this._acquisitions--;
if (this._acquisitions == 0) if (this._acquisitions == 0)
this.emit('release'); this.emit('release');
} },
isAcquired() { isAcquired() {
return this._acquisitions > 0; return this._acquisitions > 0;
} }
}; });
Signals.addSignalMethods(Hold.prototype); Signals.addSignalMethods(Hold.prototype);
var Batch = class extends Task { var Batch = new Lang.Class({
constructor(scope, tasks) { Name: 'Batch',
super(); Extends: Task,
_init(scope, tasks) {
this.parent();
this.tasks = []; this.tasks = [];
@@ -122,11 +130,11 @@ var Batch = class extends Task {
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)) {
@@ -134,11 +142,11 @@ var Batch = class extends Task {
} }
return this.tasks[this._currentTaskIndex].run(); return this.tasks[this._currentTaskIndex].run();
} },
_finish() { _finish() {
this.hold.release(); this.hold.release();
} },
nextTask() { nextTask() {
this._currentTaskIndex++; this._currentTaskIndex++;
@@ -151,7 +159,7 @@ var Batch = class extends Task {
} }
this.process(); this.process();
} },
_start() { _start() {
// acquire a hold to get released when the entire // acquire a hold to get released when the entire
@@ -159,7 +167,7 @@ var Batch = class extends Task {
this.hold = new Hold(); this.hold = new Hold();
this._currentTaskIndex = 0; this._currentTaskIndex = 0;
this.process(); this.process();
} },
run() { run() {
this._start(); this._start();
@@ -167,15 +175,18 @@ var Batch = class extends Task {
// hold may be destroyed at this point // hold may be destroyed at this point
// if we're already done running // if we're already done running
return this.hold; return this.hold;
} },
cancel() { cancel() {
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1); this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
} }
}; });
Signals.addSignalMethods(Batch.prototype); Signals.addSignalMethods(Batch.prototype);
var ConcurrentBatch = class extends Batch { var ConcurrentBatch = new Lang.Class({
Name: 'ConcurrentBatch',
Extends: Batch,
process() { process() {
let hold = this.runTask(); let hold = this.runTask();
@@ -188,10 +199,13 @@ var ConcurrentBatch = class extends Batch {
// concurrently. // concurrently.
this.nextTask(); this.nextTask();
} }
}; });
Signals.addSignalMethods(ConcurrentBatch.prototype); Signals.addSignalMethods(ConcurrentBatch.prototype);
var ConsecutiveBatch = class extends Batch { var ConsecutiveBatch = new Lang.Class({
Name: 'ConsecutiveBatch',
Extends: Batch,
process() { process() {
let hold = this.runTask(); let hold = this.runTask();
@@ -208,5 +222,5 @@ var ConsecutiveBatch = class extends Batch {
this.nextTask(); this.nextTask();
} }
} }
}; });
Signals.addSignalMethods(ConsecutiveBatch.prototype); Signals.addSignalMethods(ConsecutiveBatch.prototype);

View File

@@ -1,6 +1,9 @@
// -*- 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 Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = ` const FprintManagerIface = `
<node> <node>
@@ -23,8 +26,8 @@ function FprintManager() {
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

@@ -16,9 +16,20 @@
* 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 Lang = imports.lang;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals; 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;
@@ -39,8 +50,10 @@ 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 = class { var UserListItem = new Lang.Class({
constructor(user) { Name: 'UserListItem',
_init(user) {
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));
@@ -78,26 +91,26 @@ var UserListItem = class {
this.actor.connect('clicked', this._onClicked.bind(this)); this.actor.connect('clicked', this._onClicked.bind(this));
this._onUserChanged(); this._onUserChanged();
} },
_onUserChanged() { _onUserChanged() {
this._updateLoggedIn(); this._updateLoggedIn();
} },
_updateLoggedIn() { _updateLoggedIn() {
if (this.user.is_logged_in()) if (this.user.is_logged_in())
this.actor.add_style_pseudo_class('logged-in'); this.actor.add_style_pseudo_class('logged-in');
else else
this.actor.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);
} },
_onClicked() { _onClicked() {
this.emit('activate'); this.emit('activate');
} },
_setSelected(selected) { _setSelected(selected) {
if (selected) { if (selected) {
@@ -106,7 +119,7 @@ var UserListItem = class {
} else { } else {
this.actor.remove_style_pseudo_class('selected'); this.actor.remove_style_pseudo_class('selected');
} }
} },
showTimedLoginIndicator(time) { showTimedLoginIndicator(time) {
let hold = new Batch.Hold(); let hold = new Batch.Hold();
@@ -134,7 +147,7 @@ var UserListItem = class {
GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId'); GLib.Source.set_name_by_id(this._timedLoginTimeoutId, '[gnome-shell] this._timedLoginTimeoutId');
return hold; return hold;
} },
hideTimedLoginIndicator() { hideTimedLoginIndicator() {
if (this._timedLoginTimeoutId) { if (this._timedLoginTimeoutId) {
@@ -145,14 +158,16 @@ var UserListItem = class {
this._timedLoginIndicator.visible = false; this._timedLoginIndicator.visible = false;
this._timedLoginIndicator.scale_x = 0.; this._timedLoginIndicator.scale_x = 0.;
} }
}; });
Signals.addSignalMethods(UserListItem.prototype); Signals.addSignalMethods(UserListItem.prototype);
var UserList = class { var UserList = new Lang.Class({
constructor() { Name: 'UserList',
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' });
this.actor.set_policy(St.PolicyType.NEVER, _init() {
St.PolicyType.AUTOMATIC); this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor.set_policy(Gtk.PolicyType.NEVER,
Gtk.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',
@@ -162,7 +177,7 @@ var UserList = class {
this._items = {}; this._items = {};
this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this)); this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this));
} },
_moveFocusToItems() { _moveFocusToItems() {
let hasItems = Object.keys(this._items).length > 0; let hasItems = Object.keys(this._items).length > 0;
@@ -173,20 +188,22 @@ var UserList = class {
if (global.stage.get_key_focus() != this.actor) if (global.stage.get_key_focus() != this.actor)
return; return;
let focusSet = this.actor.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();
return false; return false;
}); });
} }
} },
_onItemActivated(activatedItem) { _onItemActivated(activatedItem) {
this.emit('activate', activatedItem); this.emit('activate', activatedItem);
} },
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
@@ -196,7 +213,7 @@ var UserList = class {
let item = this._items[userName]; let item = this._items[userName];
item.actor.sync_hover(); item.actor.sync_hover();
} }
} },
scrollToItem(item) { scrollToItem(item) {
let box = item.actor.get_allocation_box(); let box = item.actor.get_allocation_box();
@@ -209,7 +226,7 @@ var UserList = class {
{ value: value, { value: value,
time: _SCROLL_ANIMATION_TIME, time: _SCROLL_ANIMATION_TIME,
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
} },
jumpToItem(item) { jumpToItem(item) {
let box = item.actor.get_allocation_box(); let box = item.actor.get_allocation_box();
@@ -219,7 +236,7 @@ var UserList = class {
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.set_value(value); adjustment.set_value(value);
} },
getItemFromUserName(userName) { getItemFromUserName(userName) {
let item = this._items[userName]; let item = this._items[userName];
@@ -228,11 +245,11 @@ var UserList = class {
return null; return null;
return item; return item;
} },
containsUser(user) { containsUser(user) {
return this._items[user.get_user_name()] != null; return this._items[user.get_user_name()] != null;
} },
addUser(user) { addUser(user) {
if (!user.is_loaded) if (!user.is_loaded)
@@ -259,12 +276,12 @@ var UserList = class {
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.actor.connect('key-focus-in', () => this.scrollToItem(item)); item.actor.connect('key-focus-in', () => { this.scrollToItem(item); });
this._moveFocusToItems(); this._moveFocusToItems();
this.emit('item-added', item); this.emit('item-added', item);
} },
removeUser(user) { removeUser(user) {
if (!user.is_loaded) if (!user.is_loaded)
@@ -282,16 +299,18 @@ var UserList = class {
item.actor.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); Signals.addSignalMethods(UserList.prototype);
var SessionMenuButton = class { var SessionMenuButton = new Lang.Class({
constructor() { Name: 'SessionMenuButton',
_init() {
let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' }); let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
this._button = new St.Button({ style_class: 'login-dialog-session-list-button', this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
reactive: true, reactive: true,
@@ -323,22 +342,21 @@ var SessionMenuButton = class {
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;
this._populate(); this._populate();
} },
updateSensitivity(sensitive) { updateSensitivity(sensitive) {
this._button.reactive = sensitive; this._button.reactive = sensitive;
this._button.can_focus = sensitive; this._button.can_focus = sensitive;
this._menu.close(BoxPointer.PopupAnimation.NONE); this._menu.close(BoxPointer.PopupAnimation.NONE);
} },
_updateOrnament() { _updateOrnament() {
let itemIds = Object.keys(this._items); let itemIds = Object.keys(this._items);
@@ -348,7 +366,7 @@ var SessionMenuButton = class {
else else
this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE); this._items[itemIds[i]].setOrnament(PopupMenu.Ornament.NONE);
} }
} },
setActiveSession(sessionId) { setActiveSession(sessionId) {
if (sessionId == this._activeSessionId) if (sessionId == this._activeSessionId)
@@ -356,11 +374,11 @@ var SessionMenuButton = class {
this._activeSessionId = sessionId; this._activeSessionId = sessionId;
this._updateOrnament(); this._updateOrnament();
} },
close() { close() {
this._menu.close(); this._menu.close();
} },
_populate() { _populate() {
let ids = Gdm.get_session_ids(); let ids = Gdm.get_session_ids();
@@ -385,14 +403,16 @@ var SessionMenuButton = class {
}); });
} }
} }
}; });
Signals.addSignalMethods(SessionMenuButton.prototype); Signals.addSignalMethods(SessionMenuButton.prototype);
var LoginDialog = GObject.registerClass({ var LoginDialog = new Lang.Class({
Name: 'LoginDialog',
Extends: St.Widget,
Signals: { 'failed': {} }, Signals: { 'failed': {} },
}, class LoginDialog extends St.Widget {
_init(parentActor) { _init(parentActor) {
super._init({ style_class: 'login-dialog', this.parent({ style_class: 'login-dialog',
visible: false }); visible: false });
this.get_accessible().set_role(Atk.Role.WINDOW); this.get_accessible().set_role(Atk.Role.WINDOW);
@@ -401,18 +421,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();
@@ -462,8 +482,8 @@ var LoginDialog = GObject.registerClass({
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 });
@@ -479,9 +499,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();
@@ -513,7 +530,7 @@ var LoginDialog = GObject.registerClass({
// focus later // focus later
this._startupCompleteId = Main.layoutManager.connect('startup-complete', this._startupCompleteId = Main.layoutManager.connect('startup-complete',
this._updateDisableUserList.bind(this)); this._updateDisableUserList.bind(this));
} },
_getBannerAllocation(dialogBox) { _getBannerAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
@@ -527,7 +544,7 @@ var LoginDialog = GObject.registerClass({
actorBox.y2 = actorBox.y1 + natHeight; actorBox.y2 = actorBox.y1 + natHeight;
return actorBox; return actorBox;
} },
_getLogoBinAllocation(dialogBox) { _getLogoBinAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
@@ -541,7 +558,7 @@ var LoginDialog = GObject.registerClass({
actorBox.y2 = actorBox.y1 + natHeight; actorBox.y2 = actorBox.y1 + natHeight;
return actorBox; return actorBox;
} },
_getCenterActorAllocation(dialogBox, actor) { _getCenterActorAllocation(dialogBox, actor) {
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
@@ -559,7 +576,7 @@ var LoginDialog = GObject.registerClass({
actorBox.y2 = actorBox.y1 + natHeight; actorBox.y2 = actorBox.y1 + natHeight;
return actorBox; return actorBox;
} },
vfunc_allocate(dialogBox, flags) { vfunc_allocate(dialogBox, flags) {
this.set_allocation(dialogBox, flags); this.set_allocation(dialogBox, flags);
@@ -573,15 +590,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.actor.visible) { if (this._authPrompt.actor.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor); authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1; authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
} }
@@ -646,7 +667,7 @@ 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 [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth); let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
@@ -698,7 +719,7 @@ var LoginDialog = GObject.registerClass({
if (logoAllocation) if (logoAllocation)
this._logoBin.allocate(logoAllocation, flags); this._logoBin.allocate(logoAllocation, flags);
} },
_ensureUserListLoaded() { _ensureUserListLoaded() {
if (!this._userManager.is_loaded) { if (!this._userManager.is_loaded) {
@@ -714,7 +735,7 @@ var LoginDialog = GObject.registerClass({
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._loadUserList.bind(this)); let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._loadUserList.bind(this));
GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList'); GLib.Source.set_name_by_id(id, '[gnome-shell] _loadUserList');
} }
} },
_updateDisableUserList() { _updateDisableUserList() {
let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY); let disableUserList = this._settings.get_boolean(GdmUtil.DISABLE_USER_LIST_KEY);
@@ -729,7 +750,7 @@ var LoginDialog = GObject.registerClass({
if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) if (this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset(); this._authPrompt.reset();
} }
} },
_updateCancelButton() { _updateCancelButton() {
let cancelVisible; let cancelVisible;
@@ -742,7 +763,7 @@ var LoginDialog = GObject.registerClass({
cancelVisible = true; cancelVisible = true;
this._authPrompt.cancelButton.visible = cancelVisible; this._authPrompt.cancelButton.visible = cancelVisible;
} },
_updateBanner() { _updateBanner() {
let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY); let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY);
@@ -754,7 +775,7 @@ var LoginDialog = GObject.registerClass({
} else { } else {
this._bannerLabel.hide(); this._bannerLabel.hide();
} }
} },
_fadeInBannerView() { _fadeInBannerView() {
this._bannerView.show(); this._bannerView.show();
@@ -762,34 +783,33 @@ var LoginDialog = GObject.registerClass({
{ opacity: 255, { opacity: 255,
time: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
} },
_hideBannerView() { _hideBannerView() {
Tweener.removeTweens(this._bannerView); Tweener.removeTweens(this._bannerView);
this._bannerView.opacity = 0; this._bannerView.opacity = 0;
this._bannerView.hide(); this._bannerView.hide();
} },
_updateLogoTexture(cache, file) { _updateLogoTexture(cache, file) {
if (this._logoFile && !this._logoFile.equal(file)) if (this._logoFile && !this._logoFile.equal(file))
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));
}
} }
},
_updateLogo() { _updateLogo() {
let path = this._settings.get_string(GdmUtil.LOGO_KEY); let path = this._settings.get_string(GdmUtil.LOGO_KEY);
this._logoFile = path ? Gio.file_new_for_path(path) : null; this._logoFile = path ? Gio.file_new_for_path(path) : null;
this._updateLogoTexture(this._textureCache, this._logoFile); this._updateLogoTexture(this._textureCache, this._logoFile);
} },
_onPrompted() { _onPrompted() {
if (this._shouldShowSessionMenuButton()) { if (this._shouldShowSessionMenuButton()) {
@@ -799,7 +819,7 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton.updateSensitivity(false); this._sessionMenuButton.updateSensitivity(false);
} }
this._showPrompt(); this._showPrompt();
} },
_resetGreeterProxy() { _resetGreeterProxy() {
if (GLib.getenv('GDM_GREETER_TEST') != '1') { if (GLib.getenv('GDM_GREETER_TEST') != '1') {
@@ -815,7 +835,7 @@ var LoginDialog = GObject.registerClass({
this._timedLoginRequestedId = this._greeter.connect('timed-login-requested', this._timedLoginRequestedId = this._greeter.connect('timed-login-requested',
this._onTimedLoginRequested.bind(this)); this._onTimedLoginRequested.bind(this));
} }
} },
_onReset(authPrompt, beginRequest) { _onReset(authPrompt, beginRequest) {
this._resetGreeterProxy(); this._resetGreeterProxy();
@@ -836,11 +856,11 @@ var LoginDialog = GObject.registerClass({
} else { } else {
this._hideUserListAndBeginVerification(); this._hideUserListAndBeginVerification();
} }
} },
_onDefaultSessionChanged(client, sessionId) { _onDefaultSessionChanged(client, sessionId) {
this._sessionMenuButton.setActiveSession(sessionId); this._sessionMenuButton.setActiveSession(sessionId);
} },
_shouldShowSessionMenuButton() { _shouldShowSessionMenuButton() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING && if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
@@ -851,7 +871,7 @@ var LoginDialog = GObject.registerClass({
return false; return false;
return true; return true;
} },
_showPrompt() { _showPrompt() {
if (this._authPrompt.actor.visible) if (this._authPrompt.actor.visible)
@@ -863,7 +883,7 @@ var LoginDialog = GObject.registerClass({
time: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
this._fadeInBannerView(); this._fadeInBannerView();
} },
_showRealmLoginHint(realmManager, hint) { _showRealmLoginHint(realmManager, hint) {
if (!hint) if (!hint)
@@ -876,7 +896,7 @@ var LoginDialog = GObject.registerClass({
// Translators: this message is shown below the username entry field // Translators: this message is shown below the username entry field
// to clue the user in on how to login to the local network realm // to clue the user in on how to login to the local network realm
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT); this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
} },
_askForUsernameAndBeginVerification() { _askForUsernameAndBeginVerification() {
this._authPrompt.setPasswordChar(''); this._authPrompt.setPasswordChar('');
@@ -903,7 +923,7 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton.updateSensitivity(false); this._sessionMenuButton.updateSensitivity(false);
this._authPrompt.updateSensitivity(true); this._authPrompt.updateSensitivity(true);
this._showPrompt(); this._showPrompt();
} },
_loginScreenSessionActivated() { _loginScreenSessionActivated() {
if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING) if (this.opacity == 255 && this._authPrompt.verificationStatus == AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
@@ -913,7 +933,7 @@ var LoginDialog = GObject.registerClass({
{ opacity: 255, { opacity: 255,
time: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onUpdate: () => { onUpdate() {
let children = Main.layoutManager.uiGroup.get_children(); let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
@@ -921,11 +941,13 @@ var LoginDialog = GObject.registerClass({
children[i].opacity = this.opacity; children[i].opacity = this.opacity;
} }
}, },
onComplete: () => { 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();
} }); },
} onCompleteScope: this });
},
_gotGreeterSessionProxy(proxy) { _gotGreeterSessionProxy(proxy) {
this._greeterSessionProxy = proxy; this._greeterSessionProxy = proxy;
@@ -934,14 +956,14 @@ var LoginDialog = GObject.registerClass({
if (proxy.Active) if (proxy.Active)
this._loginScreenSessionActivated(); this._loginScreenSessionActivated();
}); });
} },
_startSession(serviceName) { _startSession(serviceName) {
Tweener.addTween(this, Tweener.addTween(this,
{ opacity: 0, { opacity: 0,
time: _FADE_ANIMATION_TIME, time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onUpdate: () => { onUpdate() {
let children = Main.layoutManager.uiGroup.get_children(); let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
@@ -949,14 +971,16 @@ var LoginDialog = GObject.registerClass({
children[i].opacity = this.opacity; children[i].opacity = this.opacity;
} }
}, },
onComplete: () => { onUpdateScope: this,
onComplete() {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null); 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) {
let item = this._userList.getItemFromUserName(userName); let item = this._userList.getItemFromUserName(userName);
@@ -973,10 +997,10 @@ var LoginDialog = GObject.registerClass({
hold.release(); hold.release();
}); });
hold.connect('release', () => this._userList.disconnect(signalId)); hold.connect('release', () => { this._userList.disconnect(signalId); });
return hold; return hold;
} },
_blockTimedLoginUntilIdle() { _blockTimedLoginUntilIdle() {
let hold = new Batch.Hold(); let hold = new Batch.Hold();
@@ -989,7 +1013,7 @@ var LoginDialog = GObject.registerClass({
}); });
GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginIdleTimeOutId'); GLib.Source.set_name_by_id(this._timedLoginIdleTimeOutId, '[gnome-shell] this._timedLoginIdleTimeOutId');
return hold; return hold;
} },
_startTimedLogin(userName, delay) { _startTimedLogin(userName, delay) {
let firstRun = true; let firstRun = true;
@@ -1037,7 +1061,6 @@ var LoginDialog = GObject.registerClass({
return this._blockTimedLoginUntilIdle(); return this._blockTimedLoginUntilIdle();
} else { } else {
animationTime = delay; animationTime = delay;
return null;
} }
}, },
@@ -1063,7 +1086,7 @@ var LoginDialog = GObject.registerClass({
this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks); this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
return this._timedLoginBatch.run(); return this._timedLoginBatch.run();
} },
_onTimedLoginRequested(client, userName, seconds) { _onTimedLoginRequested(client, userName, seconds) {
if (this._timedLoginBatch) if (this._timedLoginBatch)
@@ -1080,28 +1103,28 @@ var LoginDialog = GObject.registerClass({
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}); });
} },
_setUserListExpanded(expanded) { _setUserListExpanded(expanded) {
this._userList.updateStyle(expanded); this._userList.updateStyle(expanded);
this._userSelectionBox.visible = expanded; this._userSelectionBox.visible = expanded;
} },
_hideUserList() { _hideUserList() {
this._setUserListExpanded(false); this._setUserListExpanded(false);
if (this._userSelectionBox.visible) if (this._userSelectionBox.visible)
GdmUtil.cloneAndFadeOutActor(this._userSelectionBox); GdmUtil.cloneAndFadeOutActor(this._userSelectionBox);
} },
_hideUserListAskForUsernameAndBeginVerification() { _hideUserListAskForUsernameAndBeginVerification() {
this._hideUserList(); this._hideUserList();
this._askForUsernameAndBeginVerification(); this._askForUsernameAndBeginVerification();
} },
_hideUserListAndBeginVerification() { _hideUserListAndBeginVerification() {
this._hideUserList(); this._hideUserList();
this._authPrompt.begin(); this._authPrompt.begin();
} },
_showUserList() { _showUserList() {
this._ensureUserListLoaded(); this._ensureUserListLoaded();
@@ -1111,7 +1134,7 @@ var LoginDialog = GObject.registerClass({
this._setUserListExpanded(true); this._setUserListExpanded(true);
this._notListedButton.show(); this._notListedButton.show();
this._userList.actor.grab_key_focus(); this._userList.actor.grab_key_focus();
} },
_beginVerificationForItem(item) { _beginVerificationForItem(item) {
this._authPrompt.setUser(item.user); this._authPrompt.setUser(item.user);
@@ -1122,7 +1145,7 @@ var LoginDialog = GObject.registerClass({
this._authPrompt.begin({ userName: userName, this._authPrompt.begin({ userName: userName,
hold: hold }); hold: hold });
return hold; return hold;
} },
_onUserListActivated(activatedItem) { _onUserListActivated(activatedItem) {
this._user = activatedItem.user; this._user = activatedItem.user;
@@ -1132,7 +1155,7 @@ var LoginDialog = GObject.registerClass({
let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox), let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox),
this._beginVerificationForItem(activatedItem)]); this._beginVerificationForItem(activatedItem)]);
batch.run(); batch.run();
} },
_onDestroy() { _onDestroy() {
if (this._userManagerLoadedId) { if (this._userManagerLoadedId) {
@@ -1173,7 +1196,7 @@ var LoginDialog = GObject.registerClass({
this._realmManager.release(); this._realmManager.release();
this._realmManager = null; this._realmManager = null;
} }
} },
_loadUserList() { _loadUserList() {
if (this._userListLoaded) if (this._userListLoaded)
@@ -1211,7 +1234,7 @@ var LoginDialog = GObject.registerClass({
}); });
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} },
open() { open() {
Main.ctrlAltTabManager.addGroup(this, Main.ctrlAltTabManager.addGroup(this,
@@ -1230,22 +1253,22 @@ var LoginDialog = GObject.registerClass({
transition: 'easeInQuad' }); transition: 'easeInQuad' });
return true; return true;
} },
close() { close() {
Main.popModal(this); Main.popModal(this);
Main.ctrlAltTabManager.removeGroup(this); Main.ctrlAltTabManager.removeGroup(this);
} },
cancel() { cancel() {
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
} },
finish(onComplete) { finish(onComplete) {
this._authPrompt.finish(onComplete); this._authPrompt.finish(onComplete);
} },
}); });

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 Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const OVirtCredentialsIface = ` const OVirtCredentialsIface = `
@@ -27,32 +28,33 @@ function OVirtCredentials() {
return self; return self;
} }
var OVirtCredentialsManager = class { var OVirtCredentialsManager = new Lang.Class({
constructor() { Name: 'OVirtCredentialsManager',
_init() {
this._token = null; this._token = null;
this._credentials = new OVirtCredentials(); this._credentials = new OVirtCredentials();
this._credentials.connectSignal('UserAuthenticated', this._credentials.connectSignal('UserAuthenticated',
this._onUserAuthenticated.bind(this)); this._onUserAuthenticated.bind(this));
} },
_onUserAuthenticated(proxy, sender, [token]) { _onUserAuthenticated(proxy, sender, [token]) {
this._token = token; this._token = token;
this.emit('user-authenticated', token); this.emit('user-authenticated', token);
} },
hasToken() { hasToken() {
return this._token != null; return this._token != null;
} },
getToken() { getToken() {
return this._token; return this._token;
} },
resetToken() { resetToken() {
this._token = null; this._token = null;
} }
}; });
Signals.addSignalMethods(OVirtCredentialsManager.prototype); Signals.addSignalMethods(OVirtCredentialsManager.prototype);
function getOVirtCredentialsManager() { function getOVirtCredentialsManager() {

View File

@@ -1,6 +1,8 @@
// -*- 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 Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -14,12 +16,14 @@ const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm"); const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface); const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = class { var Manager = new Lang.Class({
constructor(parentActor) { Name: 'Manager',
_init(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._signalId = this._aggregateProvider.connect('g-properties-changed', this._signalId = this._aggregateProvider.connect('g-properties-changed',
@@ -27,7 +31,7 @@ var Manager = class {
if ('Realms' in properties.deep_unpack()) if ('Realms' in properties.deep_unpack())
this._reloadRealms(); this._reloadRealms();
}); });
} },
_reloadRealms() { _reloadRealms() {
let realmPaths = this._aggregateProvider.Realms; let realmPaths = this._aggregateProvider.Realms;
@@ -36,12 +40,12 @@ 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));
} }
} },
_reloadRealm(realm) { _reloadRealm(realm) {
if (!realm.Configured) { if (!realm.Configured) {
@@ -54,7 +58,7 @@ var Manager = class {
this._realms[realm.get_object_path()] = realm; this._realms[realm.get_object_path()] = realm;
this._updateLoginFormat(); this._updateLoginFormat();
} },
_onRealmLoaded(realm, error) { _onRealmLoaded(realm, error) {
if (error) if (error)
@@ -66,7 +70,7 @@ var Manager = class {
if ('Configured' in properties.deep_unpack()) if ('Configured' in properties.deep_unpack())
this._reloadRealm(realm); this._reloadRealm(realm);
}); });
} },
_updateLoginFormat() { _updateLoginFormat() {
let newLoginFormat; let newLoginFormat;
@@ -83,7 +87,7 @@ var Manager = class {
this._loginFormat = newLoginFormat; this._loginFormat = newLoginFormat;
this.emit('login-format-changed', newLoginFormat); this.emit('login-format-changed', newLoginFormat);
} }
} },
get loginFormat() { get loginFormat() {
if (this._loginFormat !== undefined) if (this._loginFormat !== undefined)
@@ -92,16 +96,16 @@ var Manager = class {
this._updateLoginFormat(); this._updateLoginFormat();
return this._loginFormat; return this._loginFormat;
} },
release() { release() {
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,13 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
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; const Tweener = imports.ui.tweener;
@@ -30,7 +36,7 @@ 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,
@@ -113,8 +119,10 @@ function cloneAndFadeOutActor(actor) {
return hold; return hold;
} }
var ShellUserVerifier = class { var ShellUserVerifier = new Lang.Class({
constructor(client, params) { Name: 'ShellUserVerifier',
_init(client, params) {
params = Params.parse(params, { reauthenticationOnly: false }); params = Params.parse(params, { reauthenticationOnly: false });
this._reauthOnly = params.reauthenticationOnly; this._reauthOnly = params.reauthenticationOnly;
@@ -157,7 +165,7 @@ var ShellUserVerifier = class {
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated', this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
this._oVirtUserAuthenticated.bind(this)); this._oVirtUserAuthenticated.bind(this));
} },
begin(userName, hold) { begin(userName, hold) {
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
@@ -175,7 +183,7 @@ var ShellUserVerifier = class {
} else { } else {
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this)); this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
} }
} },
cancel() { cancel() {
if (this._cancellable) if (this._cancellable)
@@ -185,14 +193,14 @@ var ShellUserVerifier = class {
this._userVerifier.call_cancel_sync(null); this._userVerifier.call_cancel_sync(null);
this.clear(); this.clear();
} }
} },
_clearUserVerifier() { _clearUserVerifier() {
if (this._userVerifier) { if (this._userVerifier) {
this._userVerifier.run_dispose(); this._userVerifier.run_dispose();
this._userVerifier = null; this._userVerifier = null;
} }
} },
clear() { clear() {
if (this._cancellable) { if (this._cancellable) {
@@ -202,7 +210,7 @@ var ShellUserVerifier = class {
this._clearUserVerifier(); this._clearUserVerifier();
this._clearMessageQueue(); this._clearMessageQueue();
} },
destroy() { destroy() {
this.clear(); this.clear();
@@ -216,7 +224,7 @@ var ShellUserVerifier = class {
this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId); this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId);
this._oVirtCredentialsManager = null; this._oVirtCredentialsManager = null;
} },
answerQuery(serviceName, answer) { answerQuery(serviceName, answer) {
if (!this.hasPendingMessages) { if (!this.hasPendingMessages) {
@@ -227,12 +235,12 @@ var ShellUserVerifier = class {
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null); this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
}); });
} }
} },
_getIntervalForMessage(message) { _getIntervalForMessage(message) {
// We probably could be smarter here // We probably could be smarter here
return message.length * USER_READ_TIME; return message.length * USER_READ_TIME;
} },
finishMessageQueue() { finishMessageQueue() {
if (!this.hasPendingMessages) if (!this.hasPendingMessages)
@@ -242,7 +250,7 @@ var ShellUserVerifier = class {
this.hasPendingMessages = false; this.hasPendingMessages = false;
this.emit('no-more-messages'); this.emit('no-more-messages');
} },
_queueMessageTimeout() { _queueMessageTimeout() {
if (this._messageQueue.length == 0) { if (this._messageQueue.length == 0) {
@@ -265,7 +273,7 @@ var ShellUserVerifier = class {
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout'); GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout');
} },
_queueMessage(message, messageType) { _queueMessage(message, messageType) {
let interval = this._getIntervalForMessage(message); let interval = this._getIntervalForMessage(message);
@@ -273,7 +281,7 @@ var ShellUserVerifier = class {
this.hasPendingMessages = true; this.hasPendingMessages = true;
this._messageQueue.push({ text: message, type: messageType, interval: interval }); this._messageQueue.push({ text: message, type: messageType, interval: interval });
this._queueMessageTimeout(); this._queueMessageTimeout();
} },
_clearMessageQueue() { _clearMessageQueue() {
this.finishMessageQueue(); this.finishMessageQueue();
@@ -283,7 +291,7 @@ var ShellUserVerifier = class {
this._messageQueueTimeoutId = 0; this._messageQueueTimeoutId = 0;
} }
this.emit('show-message', null, MessageType.NONE); this.emit('show-message', null, MessageType.NONE);
} },
_checkForFingerprintReader() { _checkForFingerprintReader() {
this._haveFingerprintReader = false; this._haveFingerprintReader = false;
@@ -301,12 +309,12 @@ var ShellUserVerifier = class {
this._updateDefaultService(); this._updateDefaultService();
} }
}); });
} },
_oVirtUserAuthenticated(token) { _oVirtUserAuthenticated(token) {
this._preemptingService = OVIRT_SERVICE_NAME; this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated'); this.emit('ovirt-user-authenticated');
} },
_checkForSmartcard() { _checkForSmartcard() {
let smartcardDetected; let smartcardDetected;
@@ -328,7 +336,7 @@ var ShellUserVerifier = class {
this.emit('smartcard-status-changed'); this.emit('smartcard-status-changed');
} }
} },
_reportInitError(where, error) { _reportInitError(where, error) {
logError(error, where); logError(error, where);
@@ -336,13 +344,13 @@ var ShellUserVerifier = class {
this._queueMessage(_("Authentication error"), MessageType.ERROR); this._queueMessage(_("Authentication error"), MessageType.ERROR);
this._verificationFailed(false); this._verificationFailed(false);
} },
_reauthenticationChannelOpened(client, result) { _reauthenticationChannelOpened(client, result) {
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) &&
@@ -363,13 +371,13 @@ var ShellUserVerifier = class {
this._connectSignals(); this._connectSignals();
this._beginVerification(); this._beginVerification();
this._hold.release(); this._hold.release();
} },
_userVerifierGot(client, result) { _userVerifierGot(client, result) {
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);
@@ -379,7 +387,7 @@ var ShellUserVerifier = class {
this._connectSignals(); this._connectSignals();
this._beginVerification(); this._beginVerification();
this._hold.release(); this._hold.release();
} },
_connectSignals() { _connectSignals() {
this._userVerifier.connect('info', this._onInfo.bind(this)); this._userVerifier.connect('info', this._onInfo.bind(this));
@@ -389,22 +397,22 @@ var ShellUserVerifier = class {
this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this)); this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this));
this._userVerifier.connect('reset', this._onReset.bind(this)); this._userVerifier.connect('reset', this._onReset.bind(this));
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)); this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
} },
_getForegroundService() { _getForegroundService() {
if (this._preemptingService) if (this._preemptingService)
return this._preemptingService; return this._preemptingService;
return this._defaultService; return this._defaultService;
} },
serviceIsForeground(serviceName) { serviceIsForeground(serviceName) {
return serviceName == this._getForegroundService(); return serviceName == this._getForegroundService();
} },
serviceIsDefault(serviceName) { serviceIsDefault(serviceName) {
return serviceName == this._defaultService; return serviceName == this._defaultService;
} },
_updateDefaultService() { _updateDefaultService() {
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY)) if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
@@ -418,15 +426,18 @@ var ShellUserVerifier = class {
log("no authentication service is enabled, using password authentication"); log("no authentication service is enabled, using password authentication");
this._defaultService = PASSWORD_SERVICE_NAME; this._defaultService = PASSWORD_SERVICE_NAME;
} }
} },
_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);
@@ -436,10 +447,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);
@@ -449,14 +462,14 @@ var ShellUserVerifier = class {
this._hold.release(); this._hold.release();
}); });
} }
} },
_beginVerification() { _beginVerification() {
this._startService(this._getForegroundService()); this._startService(this._getForegroundService());
if (this._userName && this._haveFingerprintReader && !this.serviceIsForeground(FINGERPRINT_SERVICE_NAME)) if (this._userName && this._haveFingerprintReader && !this.serviceIsForeground(FINGERPRINT_SERVICE_NAME))
this._startService(FINGERPRINT_SERVICE_NAME); this._startService(FINGERPRINT_SERVICE_NAME);
} },
_onInfo(client, serviceName, info) { _onInfo(client, serviceName, info) {
if (this.serviceIsForeground(serviceName)) { if (this.serviceIsForeground(serviceName)) {
@@ -471,21 +484,21 @@ var ShellUserVerifier = class {
// to indicate the user can swipe their finger instead // to indicate the user can swipe their finger instead
this._queueMessage(_("(or swipe finger)"), MessageType.HINT); this._queueMessage(_("(or swipe finger)"), MessageType.HINT);
} }
} },
_onProblem(client, serviceName, problem) { _onProblem(client, serviceName, problem) {
if (!this.serviceIsForeground(serviceName)) if (!this.serviceIsForeground(serviceName))
return; return;
this._queueMessage(problem, MessageType.ERROR); this._queueMessage(problem, MessageType.ERROR);
} },
_onInfoQuery(client, serviceName, question) { _onInfoQuery(client, serviceName, question) {
if (!this.serviceIsForeground(serviceName)) if (!this.serviceIsForeground(serviceName))
return; return;
this.emit('ask-question', serviceName, question, ''); this.emit('ask-question', serviceName, question, '');
} },
_onSecretInfoQuery(client, serviceName, secretQuestion) { _onSecretInfoQuery(client, serviceName, secretQuestion) {
if (!this.serviceIsForeground(serviceName)) if (!this.serviceIsForeground(serviceName))
@@ -498,7 +511,7 @@ var ShellUserVerifier = class {
} }
this.emit('ask-question', serviceName, secretQuestion, '\u25cf'); this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
} },
_onReset() { _onReset() {
// Clear previous attempts to authenticate // Clear previous attempts to authenticate
@@ -506,20 +519,20 @@ var ShellUserVerifier = class {
this._updateDefaultService(); this._updateDefaultService();
this.emit('reset'); this.emit('reset');
} },
_onVerificationComplete() { _onVerificationComplete() {
this.emit('verification-complete'); this.emit('verification-complete');
} },
_cancelAndReset() { _cancelAndReset() {
this.cancel(); this.cancel();
this._onReset(); this._onReset();
} },
_retry() { _retry() {
this.begin(this._userName, new Batch.Hold()); this.begin(this._userName, new Batch.Hold());
} },
_verificationFailed(retry) { _verificationFailed(retry) {
// For Not Listed / enterprise logins, immediately reset // For Not Listed / enterprise logins, immediately reset
@@ -554,7 +567,7 @@ var ShellUserVerifier = class {
} }
this.emit('verification-failed', canRetry); this.emit('verification-failed', canRetry);
} },
_onConversationStopped(client, serviceName) { _onConversationStopped(client, serviceName) {
// If the login failed with the preauthenticated oVirt credentials // If the login failed with the preauthenticated oVirt credentials
@@ -573,6 +586,6 @@ var ShellUserVerifier = class {
if (this.serviceIsForeground(serviceName)) { if (this.serviceIsForeground(serviceName)) {
this._verificationFailed(true); this._verificationFailed(true);
} }
} },
}; });
Signals.addSignalMethods(ShellUserVerifier.prototype); Signals.addSignalMethods(ShellUserVerifier.prototype);

View File

@@ -16,7 +16,6 @@
<file>misc/history.js</file> <file>misc/history.js</file>
<file>misc/ibusManager.js</file> <file>misc/ibusManager.js</file>
<file>misc/inputMethod.js</file> <file>misc/inputMethod.js</file>
<file>misc/introspect.js</file>
<file>misc/jsParse.js</file> <file>misc/jsParse.js</file>
<file>misc/keyboardManager.js</file> <file>misc/keyboardManager.js</file>
<file>misc/loginManager.js</file> <file>misc/loginManager.js</file>
@@ -64,7 +63,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 +77,12 @@
<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/remoteMenu.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

@@ -3,7 +3,7 @@
// Common utils for the extension system and the extension // Common utils for the extension system and the extension
// preferences tool // preferences tool
const Gettext = imports.gettext; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
@@ -31,7 +31,7 @@ function getCurrentExtension() {
// 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,66 +64,6 @@ function getCurrentExtension() {
return null; return null;
} }
/**
* initTranslations:
* @domain: (optional): the gettext domain to use
*
* Initialize Gettext to load translations from extensionsdir/locale.
* If @domain is not provided, it will be taken from metadata['gettext-domain']
*/
function initTranslations(domain) {
let extension = 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:
* @schema: (optional): the GSettings schema id
*
* 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:
* @required: an array of versions we're compatible with * @required: an array of versions we're compatible with
@@ -162,6 +102,8 @@ function isOutOfDate(extension) {
} }
function createExtensionObject(uuid, dir, type) { function createExtensionObject(uuid, dir, type) {
let info;
let metadataFile = dir.get_child('metadata.json'); let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) { if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json'); throw new Error('Missing metadata.json');
@@ -173,25 +115,25 @@ function createExtensionObject(uuid, dir, type) {
if (metadataContents instanceof Uint8Array) if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents); metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) { } catch (e) {
throw new Error(`Failed to load metadata.json: ${e}`); throw new Error('Failed to load metadata.json: ' + e);
} }
let meta; let meta;
try { try {
meta = JSON.parse(metadataContents); meta = JSON.parse(metadataContents);
} catch (e) { } catch (e) {
throw new Error(`Failed to parse metadata.json: ${e}`); throw new Error('Failed to parse metadata.json: ' + e);
} }
let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) { for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i]; let prop = requiredProperties[i];
if (!meta[prop]) { if (!meta[prop]) {
throw new Error(`missing "${prop}" property in metadata.json`); throw new Error('missing "' + prop + '" property in metadata.json');
} }
} }
if (uuid != meta.uuid) { if (uuid != meta.uuid) {
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`); throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
} }
let extension = {}; let extension = {};
@@ -218,7 +160,9 @@ function installImporter(extension) {
imports.searchPath = oldSearchPath; imports.searchPath = oldSearchPath;
} }
var ExtensionFinder = class { var ExtensionFinder = new Lang.Class({
Name: 'ExtensionFinder',
_loadExtension(extensionDir, info, perUserDir) { _loadExtension(extensionDir, info, perUserDir) {
let fileType = info.get_file_type(); let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY) if (fileType != Gio.FileType.DIRECTORY)
@@ -235,12 +179,12 @@ var ExtensionFinder = class {
: ExtensionType.SYSTEM; : ExtensionType.SYSTEM;
try { try {
extension = createExtensionObject(uuid, extensionDir, type); extension = createExtensionObject(uuid, extensionDir, type);
} catch (e) { } catch(e) {
logError(e, 'Could not load extension %s'.format(uuid)); logError(e, 'Could not load extension %s'.format(uuid));
return; return;
} }
this.emit('extension-found', extension); this.emit('extension-found', extension);
} },
scanExtensions() { scanExtensions() {
let perUserDir = Gio.File.new_for_path(global.userdatadir); let perUserDir = Gio.File.new_for_path(global.userdatadir);
@@ -248,5 +192,5 @@ var ExtensionFinder = class {
this._loadExtension(dir, info, perUserDir); this._loadExtension(dir, info, perUserDir);
}); });
} }
}; });
Signals.addSignalMethods(ExtensionFinder.prototype); Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@@ -1,7 +1,10 @@
// -*- 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 Lang = imports.lang;
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();
@@ -36,7 +39,7 @@ 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());
@@ -57,7 +60,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());
@@ -86,11 +89,11 @@ function loadInterfaceXML(iface) {
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,6 +1,8 @@
// -*- 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 Lang = imports.lang;
const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;

View File

@@ -1,13 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Params = imports.misc.params; const Params = imports.misc.params;
var DEFAULT_LIMIT = 512; var DEFAULT_LIMIT = 512;
var HistoryManager = class { var HistoryManager = new Lang.Class({
constructor(params) { Name: 'HistoryManager',
_init(params) {
params = Params.parse(params, { gsettingsKey: null, params = Params.parse(params, { gsettingsKey: null,
limit: DEFAULT_LIMIT, limit: DEFAULT_LIMIT,
entry: null }); entry: null });
@@ -18,7 +21,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 {
@@ -31,12 +34,12 @@ var HistoryManager = class {
this._entry.connect('key-press-event', this._entry.connect('key-press-event',
this._onEntryKeyPress.bind(this)); this._onEntryKeyPress.bind(this));
} }
} },
_historyChanged() { _historyChanged() {
this._history = global.settings.get_strv(this._key); this._history = global.settings.get_strv(this._key);
this._historyIndex = this._history.length; this._historyIndex = this._history.length;
} },
_setPrevItem(text) { _setPrevItem(text) {
if (this._historyIndex <= 0) if (this._historyIndex <= 0)
@@ -47,7 +50,7 @@ var HistoryManager = class {
this._historyIndex--; this._historyIndex--;
this._indexChanged(); this._indexChanged();
return true; return true;
} },
_setNextItem(text) { _setNextItem(text) {
if (this._historyIndex >= this._history.length) if (this._historyIndex >= this._history.length)
@@ -58,7 +61,7 @@ var HistoryManager = class {
this._historyIndex++; this._historyIndex++;
this._indexChanged(); this._indexChanged();
return true; return true;
} },
lastItem() { lastItem() {
if (this._historyIndex != this._history.length) { if (this._historyIndex != this._history.length) {
@@ -66,8 +69,8 @@ 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) {
if (this._history.length == 0 || if (this._history.length == 0 ||
@@ -78,7 +81,7 @@ var HistoryManager = class {
this._save(); this._save();
} }
this._historyIndex = this._history.length; this._historyIndex = this._history.length;
} },
_onEntryKeyPress(entry, event) { _onEntryKeyPress(entry, event) {
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
@@ -88,7 +91,7 @@ var HistoryManager = class {
return this._setNextItem(entry.get_text()); return this._setNextItem(entry.get_text());
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} },
_indexChanged() { _indexChanged() {
let current = this._history[this._historyIndex] || ''; let current = this._history[this._historyIndex] || '';
@@ -96,7 +99,7 @@ var HistoryManager = class {
if (this._entry) if (this._entry)
this._entry.set_text(current); this._entry.set_text(current);
} },
_save() { _save() {
if (this._history.length > this._limit) if (this._history.length > this._limit)
@@ -105,5 +108,5 @@ var HistoryManager = class {
if (this._key) if (this._key)
global.settings.set_strv(this._key, this._history); global.settings.set_strv(this._key, this._history);
} }
}; });
Signals.addSignalMethods(HistoryManager.prototype); Signals.addSignalMethods(HistoryManager.prototype);

View File

@@ -1,9 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Gio, GLib, IBus } = imports.gi; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop; 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
@@ -29,20 +32,21 @@ function getIBusManager() {
return _ibusManager; return _ibusManager;
} }
var IBusManager = class { var IBusManager = new Lang.Class({
constructor() { Name: 'IBusManager',
IBus.init();
// This is the longest we'll keep the keyboard frozen until an input // This is the longest we'll keep the keyboard frozen until an input
// source is active. // source is active.
this._MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms _MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
this._PRELOAD_ENGINES_DELAY_TIME = 30; // sec _PRELOAD_ENGINES_DELAY_TIME: 30, // sec
_init() {
IBus.init();
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;
@@ -56,16 +60,16 @@ var IBusManager = class {
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this)); this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
this._spawn(); this._spawn();
} },
_spawn() { _spawn() {
try { try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'], Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
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);
}
} }
},
_clear() { _clear() {
if (this._panelService) if (this._panelService)
@@ -73,7 +77,7 @@ var IBusManager = class {
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;
@@ -81,7 +85,7 @@ var IBusManager = class {
this.emit('ready', false); this.emit('ready', false);
this._spawn(); this._spawn();
} },
_onConnected() { _onConnected() {
this._ibus.list_engines_async(-1, null, this._initEngines.bind(this)); this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
@@ -89,20 +93,20 @@ var IBusManager = class {
IBus.BusNameFlag.REPLACE_EXISTING, IBus.BusNameFlag.REPLACE_EXISTING,
-1, null, -1, null,
this._initPanelService.bind(this)); this._initPanelService.bind(this));
} },
_initEngines(ibus, result) { _initEngines(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result); let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) { 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();
} else { } else {
this._clear(); this._clear();
} }
} },
_initPanelService(ibus, result) { _initPanelService(ibus, result) {
let success = this._ibus.request_name_async_finish(result); let success = this._ibus.request_name_async_finish(result);
@@ -119,7 +123,7 @@ var IBusManager = class {
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
@@ -138,7 +142,7 @@ var IBusManager = class {
engine = this._ibus.get_global_engine_async_finish(result); 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());
@@ -147,12 +151,13 @@ var IBusManager = class {
} else { } else {
this._clear(); this._clear();
} }
} },
_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);
} },
_engineChanged(bus, engineName) { _engineChanged(bus, engineName) {
if (!this._ready) if (!this._ready)
@@ -173,26 +178,26 @@ var IBusManager = class {
this.emit('properties-registered', this._currentEngineName, props); this.emit('properties-registered', this._currentEngineName, props);
}); });
} },
_updateProperty(panel, prop) { _updateProperty(panel, prop) {
this.emit('property-updated', this._currentEngineName, prop); this.emit('property-updated', this._currentEngineName, prop);
} },
_setContentType(panel, purpose, hints) { _setContentType(panel, purpose, hints) {
this.emit('set-content-type', purpose, hints); this.emit('set-content-type', purpose, hints);
} },
activateProperty(key, state) { activateProperty(key, state) {
this._panelService.property_activate(key, state); this._panelService.property_activate(key, state);
} },
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) {
// Send id even if id == this._currentEngineName // Send id even if id == this._currentEngineName
@@ -206,7 +211,7 @@ var IBusManager = class {
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME, this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback || null); null, callback || null);
} },
preloadEngines(ids) { preloadEngines(ids) {
if (!this._ibus || ids.length == 0) if (!this._ibus || ids.length == 0)
@@ -228,6 +233,6 @@ var IBusManager = class {
this._preloadEnginesId = 0; this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
} },
}; });
Signals.addSignalMethods(IBusManager.prototype); Signals.addSignalMethods(IBusManager.prototype);

View File

@@ -1,21 +1,23 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GLib, GObject, IBus } = imports.gi; const Clutter = imports.gi.Clutter;
const IBus = imports.gi.IBus;
const Keyboard = imports.ui.status.keyboard; const Keyboard = imports.ui.status.keyboard;
const Lang = imports.lang;
const Signals = imports.signals;
var HIDE_PANEL_TIME = 50; var InputMethod = new Lang.Class({
Name: 'InputMethod',
Extends: Clutter.InputMethod,
var InputMethod = GObject.registerClass(
class InputMethod extends Clutter.InputMethod {
_init() { _init() {
super._init(); this.parent();
this._hints = 0; this._hints = 0;
this._purpose = 0; this._purpose = 0;
this._enabled = true;
this._currentFocus = null; this._currentFocus = null;
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));
@@ -28,11 +30,11 @@ class InputMethod extends Clutter.InputMethod {
if (this._ibus.is_connected()) if (this._ibus.is_connected())
this._onConnected(); this._onConnected();
} },
get currentFocus() { get currentFocus() {
return this._currentFocus; return this._currentFocus;
} },
_updateCapabilities() { _updateCapabilities() {
let caps = 0; let caps = 0;
@@ -47,19 +49,21 @@ class InputMethod extends Clutter.InputMethod {
if (this._context) if (this._context)
this._context.set_capabilities(caps); this._context.set_capabilities(caps);
} },
_onSourceChanged() { _onSourceChanged() {
this._currentSource = this._inputSourceManager.currentSource; this._currentSource = this._inputSourceManager.currentSource;
} },
_onConnected() { _onConnected() {
this._ibus.create_input_context_async ('gnome-shell', -1, null, this._ibus.create_input_context_async ('gnome-shell', -1, null,
this._setContext.bind(this)); this._setContext.bind(this));
} },
_setContext(bus, res) { _setContext(bus, res) {
this._context = this._ibus.create_input_context_async_finish(res); this._context = this._ibus.create_input_context_async_finish(res);
this._context.connect('enabled', () => { this._enabled = true });
this._context.connect('disabled', () => { this._enabled = false });
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));
@@ -68,29 +72,30 @@ class InputMethod extends Clutter.InputMethod {
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this)); this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
this._updateCapabilities(); this._updateCapabilities();
} },
_clear() { _clear() {
this._context = null; this._context = null;
this._hints = 0; this._hints = 0;
this._purpose = 0; this._purpose = 0;
this._preeditStr = ''; this._enabled = false;
this._preeditStr = ''
this._preeditPos = 0; this._preeditPos = 0;
this._preeditVisible = false; this._preeditVisible = false;
} },
_emitRequestSurrounding() { _emitRequestSurrounding() {
if (this._context.needs_surrounding_text()) if (this._context.needs_surrounding_text())
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(context) { _onDeleteSurroundingText(context) {
this.delete_surrounding(); this.delete_surrounding();
} },
_onUpdatePreeditText(context, text, pos, visible) { _onUpdatePreeditText(context, text, pos, visible) {
if (text == null) if (text == null)
@@ -106,17 +111,17 @@ class InputMethod extends Clutter.InputMethod {
this._preeditStr = preedit; this._preeditStr = preedit;
this._preeditPos = pos; this._preeditPos = pos;
this._preeditVisible = visible; this._preeditVisible = visible;
} },
_onShowPreeditText(context) { _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(context) { _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;
@@ -130,7 +135,7 @@ class InputMethod extends Clutter.InputMethod {
time = global.display.get_current_time_roundtrip(); time = global.display.get_current_time_roundtrip();
this.forward_key(keyval, keycode + 8, state & Clutter.ModifierType.MODIFIER_MASK, time, press); this.forward_key(keyval, keycode + 8, state & Clutter.ModifierType.MODIFIER_MASK, time, press);
} },
vfunc_focus_in(focus) { vfunc_focus_in(focus) {
this._currentFocus = focus; this._currentFocus = focus;
@@ -139,12 +144,7 @@ class InputMethod extends Clutter.InputMethod {
this._updateCapabilities(); 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;
@@ -158,13 +158,7 @@ class InputMethod extends Clutter.InputMethod {
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() {
if (this._context) { if (this._context) {
@@ -177,7 +171,7 @@ class InputMethod extends Clutter.InputMethod {
this.set_preedit_text(null, 0); this.set_preedit_text(null, 0);
this._preeditStr = null; this._preeditStr = null;
} }
} },
vfunc_set_cursor_location(rect) { vfunc_set_cursor_location(rect) {
if (this._context) { if (this._context) {
@@ -185,7 +179,7 @@ class InputMethod extends Clutter.InputMethod {
rect.get_width(), rect.get_height()); rect.get_width(), rect.get_height());
this._emitRequestSurrounding(); this._emitRequestSurrounding();
} }
} },
vfunc_set_surrounding(text, cursor, anchor) { vfunc_set_surrounding(text, cursor, anchor) {
if (!this._context || !text) if (!this._context || !text)
@@ -193,7 +187,7 @@ class InputMethod extends Clutter.InputMethod {
let ibusText = IBus.Text.new_from_string(text); let ibusText = IBus.Text.new_from_string(text);
this._context.set_surrounding_text(ibusText, cursor, anchor); this._context.set_surrounding_text(ibusText, cursor, anchor);
} },
vfunc_update_content_hints(hints) { vfunc_update_content_hints(hints) {
let ibusHints = 0; let ibusHints = 0;
@@ -213,7 +207,7 @@ class InputMethod extends Clutter.InputMethod {
this._hints = ibusHints; this._hints = ibusHints;
if (this._context) if (this._context)
this._context.set_content_type(this._purpose, this._hints); this._context.set_content_type(this._purpose, this._hints);
} },
vfunc_update_content_purpose(purpose) { vfunc_update_content_purpose(purpose) {
let ibusPurpose = 0; let ibusPurpose = 0;
@@ -239,10 +233,10 @@ class InputMethod extends Clutter.InputMethod {
this._purpose = ibusPurpose; this._purpose = ibusPurpose;
if (this._context) if (this._context)
this._context.set_content_type(this._purpose, this._hints); this._context.set_content_type(this._purpose, this._hints);
} },
vfunc_filter_key_event(event) { vfunc_filter_key_event(event) {
if (!this._context) if (!this._context || !this._enabled)
return false; return false;
if (!this._currentSource) if (!this._currentSource)
return false; return false;
@@ -262,9 +256,9 @@ class InputMethod extends Clutter.InputMethod {
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) {
log(`Error processing key on IM: ${e.message}`); log('Error processing key on IM: ' + e.message);
} }
}); });
return true; return true;
} },
}); });

View File

@@ -1,172 +0,0 @@
const { Gio, GLib, Meta, Shell } = imports.gi;
const INTROSPECT_SCHEMA = 'org.gnome.shell';
const INTROSPECT_KEY = 'introspect';
const APP_WHITELIST = ['org.freedesktop.impl.portal.desktop.gtk'];
const { loadInterfaceXML } = imports.misc.fileUtils;
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
var IntrospectService = class {
constructor() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(IntrospectDBusIface,
this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/Introspect');
Gio.DBus.session.own_name('org.gnome.Shell.Introspect',
Gio.BusNameOwnerFlags.REPLACE,
null, null);
this._runningApplications = {};
this._runningApplicationsDirty = true;
this._activeApplication = null;
this._activeApplicationDirty = true;
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('app-state-changed',
() => {
this._runningApplicationsDirty = true;
this._syncRunningApplications();
});
this._settings = new Gio.Settings({ schema_id: INTROSPECT_SCHEMA });
let tracker = Shell.WindowTracker.get_default();
tracker.connect('notify::focus-app',
() => {
this._activeApplicationDirty = true;
this._syncRunningApplications();
});
this._syncRunningApplications();
}
_isStandaloneApp(app) {
return app.get_windows().some(w => w.transient_for == null);
}
_isIntrospectEnabled() {
return this._settings.get_boolean(INTROSPECT_KEY);
}
_isSenderWhitelisted(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() {
let tracker = Shell.WindowTracker.get_default();
let apps = this._appSystem.get_running();
let seatName = "seat0";
let newRunningApplications = {};
let newActiveApplication = null;
let focusedApp = tracker.focus_app;
for (let app of apps) {
let appInfo = {};
let isAppActive = (focusedApp == app);
if (!this._isStandaloneApp(app))
continue;
if (isAppActive) {
appInfo['active-on-seats'] = new GLib.Variant('as', [seatName]);
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;
}
if (this._runningApplicationsDirty ||
(this._activeApplicationDirty &&
this._activeApplication != newActiveApplication)) {
this._runningApplications = newRunningApplications;
this._activeApplication = newActiveApplication;
this._dbusImpl.emit_signal('RunningApplicationsChanged', null);
}
this._runningApplicationsDirty = false;
this._activeApplicationDirty = false;
}
_isEligibleWindow(window) {
if (window.is_override_redirect())
return false;
let type = window.get_window_type();
return (type == Meta.WindowType.NORMAL ||
type == Meta.WindowType.DIALOG ||
type == Meta.WindowType.MODAL_DIALOG ||
type == Meta.WindowType.UTILITY);
}
GetRunningApplicationsAsync(params, invocation) {
if (!this._isIntrospectEnabled() &&
!this._isSenderWhitelisted(invocation.get_sender())) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed');
return;
}
invocation.return_value(new GLib.Variant('(a{sa{sv}})', [this._runningApplications]));
}
GetWindowsAsync(params, invocation) {
let focusWindow = global.display.get_focus_window();
let apps = this._appSystem.get_running();
let windowsList = {};
if (!this._isIntrospectEnabled()) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed');
return;
}
for (let app of apps) {
let windows = app.get_windows();
for (let window of windows) {
if (!this._isEligibleWindow(window))
continue;
let windowId = window.get_id();
let frameRect = window.get_frame_rect();
let title = window.get_title();
let wmClass = window.get_wm_class();
let sandboxedAppId = window.get_sandboxed_app_id();
windowsList[windowId] = {
'app-id': GLib.Variant.new('s', app.get_id()),
'client-type': GLib.Variant.new('u', window.get_client_type()),
'is-hidden': GLib.Variant.new('b', window.is_hidden()),
'has-focus': GLib.Variant.new('b', (window == focusWindow)),
'width': GLib.Variant.new('u', frameRect.width),
'height': GLib.Variant.new('u', frameRect.height)
};
// These properties may not be available for all windows:
if (title != null)
windowsList[windowId]['title'] = GLib.Variant.new('s', title);
if (wmClass != null)
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]));
}
};

View File

@@ -51,14 +51,14 @@ 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;
} }
} }
@@ -68,7 +68,7 @@ function findMatchingQuote(expr, offset) {
// 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;
} }
} }
@@ -81,7 +81,7 @@ 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];
function findTheBrace(expr, offset) { function findTheBrace(expr, offset) {
if (offset < 0) { if (offset < 0) {
@@ -117,11 +117,11 @@ 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);
} }
@@ -168,7 +168,7 @@ 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 );

View File

@@ -1,6 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { GLib, GnomeDesktop, Meta } = imports.gi; const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -35,20 +38,22 @@ function holdKeyboard() {
global.display.freeze_keyboard(global.get_current_time()); global.display.freeze_keyboard(global.get_current_time());
} }
var KeyboardManager = class { var KeyboardManager = new Lang.Class({
constructor() { Name: 'KeyboardManager',
// The XKB protocol doesn't allow for more that 4 layouts in a // The XKB protocol doesn't allow for more that 4 layouts in a
// keymap. Wayland doesn't impose this limit and libxkbcommon can // keymap. Wayland doesn't impose this limit and libxkbcommon can
// handle up to 32 layouts but since we need to support X clients // handle up to 32 layouts but since we need to support X clients
// even as a Wayland compositor, we can't bump this. // even as a Wayland compositor, we can't bump this.
this.MAX_LAYOUTS_PER_GROUP = 4; MAX_LAYOUTS_PER_GROUP: 4,
_init() {
this._xkbInfo = getXkbInfo(); this._xkbInfo = getXkbInfo();
this._current = null; this._current = null;
this._localeLayoutInfo = this._getLocaleLayout(); this._localeLayoutInfo = this._getLocaleLayout();
this._layoutInfos = {}; this._layoutInfos = {};
this._currentKeymap = null; this._currentKeymap = null;
} },
_applyLayoutGroup(group) { _applyLayoutGroup(group) {
let options = this._buildOptionsString(); let options = this._buildOptionsString();
@@ -60,13 +65,13 @@ 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);
} },
_applyLayoutGroupIndex(idx) { _applyLayoutGroupIndex(idx) {
Meta.get_backend().lock_layout_group(idx); Meta.get_backend().lock_layout_group(idx);
} },
apply(id) { apply(id) {
let info = this._layoutInfos[id]; let info = this._layoutInfos[id];
@@ -82,7 +87,7 @@ var KeyboardManager = class {
} }
this._current = info; this._current = info;
} },
reapply() { reapply() {
if (!this._current) if (!this._current)
@@ -90,7 +95,7 @@ var KeyboardManager = class {
this._applyLayoutGroup(this._current.group); this._applyLayoutGroup(this._current.group);
this._applyLayoutGroupIndex(this._current.groupIndex); this._applyLayoutGroupIndex(this._current.groupIndex);
} },
setUserLayouts(ids) { setUserLayouts(ids) {
this._current = null; this._current = null;
@@ -121,11 +126,11 @@ var KeyboardManager = class {
i += 1; i += 1;
} }
} },
_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);
@@ -138,21 +143,21 @@ var KeyboardManager = class {
return { layout: _layout, variant: _variant }; return { layout: _layout, variant: _variant };
else else
return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT }; return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
} },
_buildGroupStrings(_group) { _buildGroupStrings(_group) {
let group = _group.concat(this._localeLayoutInfo); let group = _group.concat(this._localeLayoutInfo);
let layouts = group.map(g => g.layout).join(','); let layouts = group.map(g => g.layout).join(',');
let variants = group.map(g => g.variant).join(','); let variants = group.map(g => g.variant).join(',');
return [layouts, variants]; return [layouts, variants];
} },
setKeyboardOptions(options) { setKeyboardOptions(options) {
this._xkbOptions = options; this._xkbOptions = options;
} },
_buildOptionsString() { _buildOptionsString() {
let options = this._xkbOptions.join(','); let options = this._xkbOptions.join(',');
return options; return options;
} }
}; });

View File

@@ -1,6 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { GLib, Gio } = imports.gi; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
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;
@@ -43,33 +47,11 @@ 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;
/** /**
@@ -88,8 +70,10 @@ function getLoginManager() {
return _loginManager; return _loginManager;
} }
var LoginManagerSystemd = class { var LoginManagerSystemd = new Lang.Class({
constructor() { Name: 'LoginManagerSystemd',
_init() {
this._proxy = new SystemdLoginManager(Gio.DBus.system, this._proxy = new SystemdLoginManager(Gio.DBus.system,
'org.freedesktop.login1', 'org.freedesktop.login1',
'/org/freedesktop/login1'); '/org/freedesktop/login1');
@@ -98,7 +82,7 @@ var LoginManagerSystemd = class {
'/org/freedesktop/login1/user/self'); '/org/freedesktop/login1/user/self');
this._proxy.connectSignal('PrepareForSleep', this._proxy.connectSignal('PrepareForSleep',
this._prepareForSleep.bind(this)); this._prepareForSleep.bind(this));
} },
getCurrentSessionProxy(callback) { getCurrentSessionProxy(callback) {
if (this._currentSession) { if (this._currentSession) {
@@ -145,7 +129,7 @@ var LoginManagerSystemd = class {
callback(this._currentSession); callback(this._currentSession);
} }
}); });
} },
canSuspend(asyncCallback) { canSuspend(asyncCallback) {
this._proxy.CanSuspendRemote((result, error) => { this._proxy.CanSuspendRemote((result, error) => {
@@ -157,7 +141,7 @@ var LoginManagerSystemd = class {
asyncCallback(canSuspend, needsAuth); asyncCallback(canSuspend, needsAuth);
} }
}); });
} },
listSessions(asyncCallback) { listSessions(asyncCallback) {
this._proxy.ListSessionsRemote((result, error) => { this._proxy.ListSessionsRemote((result, error) => {
@@ -166,11 +150,11 @@ var LoginManagerSystemd = class {
else else
asyncCallback(result[0]); asyncCallback(result[0]);
}); });
} },
suspend() { suspend() {
this._proxy.SuspendRemote(true); this._proxy.SuspendRemote(true);
} },
inhibit(reason, callback) { inhibit(reason, callback) {
let inVariant = GLib.Variant.new('(ssss)', let inVariant = GLib.Variant.new('(ssss)',
@@ -185,41 +169,43 @@ var LoginManagerSystemd = class {
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: 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);
} }
}); });
} },
_prepareForSleep(proxy, sender, [aboutToSuspend]) { _prepareForSleep(proxy, sender, [aboutToSuspend]) {
this.emit('prepare-for-sleep', aboutToSuspend); this.emit('prepare-for-sleep', aboutToSuspend);
} }
}; });
Signals.addSignalMethods(LoginManagerSystemd.prototype); Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = class { var LoginManagerDummy = new Lang.Class({
Name: 'LoginManagerDummy',
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
} },
canSuspend(asyncCallback) { canSuspend(asyncCallback) {
asyncCallback(false, false); asyncCallback(false, false);
} },
listSessions(asyncCallback) { listSessions(asyncCallback) {
asyncCallback([]); asyncCallback([]);
} },
suspend() { suspend() {
this.emit('prepare-for-sleep', true); this.emit('prepare-for-sleep', true);
this.emit('prepare-for-sleep', false); this.emit('prepare-for-sleep', false);
} },
inhibit(reason, callback) { inhibit(reason, callback) {
callback(null); callback(null);
} }
}; });
Signals.addSignalMethods(LoginManagerDummy.prototype); Signals.addSignalMethods(LoginManagerDummy.prototype);

View File

@@ -1,6 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Gio, NMA } = imports.gi; const Gio = imports.gi.Gio;
const Lang = imports.lang;
const NMA = imports.gi.NMA;
const Signals = imports.signals; const Signals = imports.signals;
const { loadInterfaceXML } = imports.misc.fileUtils; const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -26,33 +28,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 +73,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();
@@ -98,8 +100,10 @@ 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 ModemGsm = class { var ModemGsm = new Lang.Class({
constructor(path) { Name: 'ModemGsm',
_init(path) {
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.signal_quality = 0;
@@ -135,11 +139,13 @@ var ModemGsm = class {
this.emit('notify::signal-quality'); this.emit('notify::signal-quality');
}); });
} }
}; });
Signals.addSignalMethods(ModemGsm.prototype); Signals.addSignalMethods(ModemGsm.prototype);
var ModemCdma = class { var ModemCdma = new Lang.Class({
constructor(path) { Name: 'ModemCdma',
_init(path) {
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.signal_quality = 0;
@@ -163,7 +169,7 @@ var ModemCdma = class {
} }
this.emit('notify::signal-quality'); this.emit('notify::signal-quality');
}); });
} },
_refreshServingSystem() { _refreshServingSystem() {
this._proxy.GetServingSystemRemote(([result], err) => { this._proxy.GetServingSystemRemote(([result], err) => {
@@ -173,12 +179,12 @@ var ModemCdma = class {
} else { } else {
let [bandClass, band, sid] = result; let [bandClass, band, sid] = result;
this.operator_name = _findProviderForSid(sid); this.operator_name = _findProviderForSid(sid)
} }
this.emit('notify::operator-name'); this.emit('notify::operator-name');
}); });
} }
}; });
Signals.addSignalMethods(ModemCdma.prototype); Signals.addSignalMethods(ModemCdma.prototype);
@@ -195,8 +201,10 @@ 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 = class { var BroadbandModem = new Lang.Class({
constructor(path, capabilities) { Name: 'BroadbandModem',
_init(path, capabilities) {
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path); this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', 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);
@@ -221,40 +229,40 @@ var BroadbandModem = class {
this._reloadCdmaOperatorName(); this._reloadCdmaOperatorName();
}); });
this._reloadCdmaOperatorName(); this._reloadCdmaOperatorName();
} },
_reloadSignalQuality() { _reloadSignalQuality() {
let [quality, recent] = this._proxy.SignalQuality; let [quality, recent] = this._proxy.SignalQuality;
this.signal_quality = quality; this.signal_quality = quality;
this.emit('notify::signal-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.operator_name = newName; this.operator_name = new_name;
this.emit('notify::operator-name'); this.emit('notify::operator-name');
} },
_reload3gppOperatorName() { _reload3gppOperatorName() {
let name = this._proxy_3gpp.OperatorName; let name = this._proxy_3gpp.OperatorName;
let code = this._proxy_3gpp.OperatorCode; let code = this._proxy_3gpp.OperatorCode;
this.operator_name_3gpp = _findProviderForMccMnc(name, code); this.operator_name_3gpp = _findProviderForMccMnc(name, code);
this._reloadOperatorName(); this._reloadOperatorName();
} },
_reloadCdmaOperatorName() { _reloadCdmaOperatorName() {
let sid = this._proxy_cdma.Sid; let sid = this._proxy_cdma.Sid;
this.operator_name_cdma = _findProviderForSid(sid); this.operator_name_cdma = _findProviderForSid(sid);
this._reloadOperatorName(); this._reloadOperatorName();
} }
}; });
Signals.addSignalMethods(BroadbandModem.prototype); Signals.addSignalMethods(BroadbandModem.prototype);

View File

@@ -1,6 +1,8 @@
// -*- 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 Lang = imports.lang;
const Params = imports.misc.params; const Params = imports.misc.params;
const Signals = imports.signals; const Signals = imports.signals;
@@ -25,8 +27,9 @@ const ObjectManagerIface = `
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface); const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
var ObjectManager = class { var ObjectManager = new Lang.Class({
constructor(params) { Name: 'ObjectManager',
_init(params) {
params = Params.parse(params, { connection: null, params = Params.parse(params, { connection: null,
name: null, name: null,
objectPath: null, objectPath: null,
@@ -60,7 +63,7 @@ var ObjectManager = class {
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT, this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable, this._cancellable,
this._onManagerProxyLoaded.bind(this)); this._onManagerProxyLoaded.bind(this));
} },
_tryToCompleteLoad() { _tryToCompleteLoad() {
if (this._numLoadInhibitors == 0) if (this._numLoadInhibitors == 0)
@@ -71,7 +74,7 @@ var ObjectManager = class {
if (this._onLoaded) if (this._onLoaded)
this._onLoaded(); this._onLoaded();
} }
} },
_addInterface(objectPath, interfaceName, onFinished) { _addInterface(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName]; let info = this._interfaceInfos[interfaceName];
@@ -89,11 +92,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();
@@ -123,7 +129,7 @@ var ObjectManager = class {
if (onFinished) if (onFinished)
onFinished(); onFinished();
}); });
} },
_removeInterface(objectPath, interfaceName) { _removeInterface(objectPath, interfaceName) {
if (!this._objects[objectPath]) if (!this._objects[objectPath])
@@ -149,13 +155,14 @@ var ObjectManager = class {
delete this._objects[objectPath]; delete this._objects[objectPath];
this.emit('object-removed', objectPath); this.emit('object-removed', objectPath);
} }
} },
_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;
@@ -187,13 +194,13 @@ var ObjectManager = class {
if (this._managerProxy.g_name_owner) if (this._managerProxy.g_name_owner)
this._onNameAppeared(); this._onNameAppeared();
} },
_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();
@@ -225,7 +232,7 @@ var ObjectManager = class {
} }
this._tryToCompleteLoad(); this._tryToCompleteLoad();
}); });
} },
_onNameVanished() { _onNameVanished() {
let objectPaths = Object.keys(this._objects); let objectPaths = Object.keys(this._objects);
@@ -241,14 +248,14 @@ var ObjectManager = class {
this._removeInterface(objectPath, interfaceName); this._removeInterface(objectPath, interfaceName);
} }
} }
} },
_registerInterfaces(interfaces) { _registerInterfaces(interfaces) {
for (let i = 0; i < interfaces.length; i++) { for (let i = 0; i < interfaces.length; i++) {
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]); let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
this._interfaceInfos[info.name] = info; this._interfaceInfos[info.name] = info;
} }
} },
getProxy(objectPath, interfaceName) { getProxy(objectPath, interfaceName) {
let object = this._objects[objectPath]; let object = this._objects[objectPath];
@@ -257,7 +264,7 @@ var ObjectManager = class {
return null; return null;
return object[interfaceName]; return object[interfaceName];
} },
getProxiesForInterface(interfaceName) { getProxiesForInterface(interfaceName) {
let proxyList = this._interfaces[interfaceName]; let proxyList = this._interfaces[interfaceName];
@@ -266,7 +273,7 @@ var ObjectManager = class {
return []; return [];
return proxyList; return proxyList;
} },
getAllProxies() { getAllProxies() {
let proxies = []; let proxies = [];
@@ -276,8 +283,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));
} }
@@ -285,5 +292,5 @@ var ObjectManager = class {
return proxies; return proxies;
} }
}; });
Signals.addSignalMethods(ObjectManager.prototype); Signals.addSignalMethods(ObjectManager.prototype);

View File

@@ -1,7 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
// parse: // parse:
// @params: caller-provided parameter object, or %null // @params: caller-provided parameter object, or %null
// @defaults-provided defaults object // @defaults-provided defaults object
@@ -16,14 +14,22 @@ const Lang = imports.lang;
// //
// 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 = {}; for (prop in defaults) {
Lang.copyProperties(defaults, defaultsCopy); if (!(prop in params))
return Object.assign(defaultsCopy, params); ret[prop] = defaults[prop];
}
return ret;
} }

View File

@@ -12,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,6 +1,8 @@
// -*- 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 Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager; const ObjectManager = imports.misc.objectManager;
@@ -24,16 +26,17 @@ function getSmartcardManager() {
return _smartcardManager; return _smartcardManager;
} }
var SmartcardManager = class { var SmartcardManager = new Lang.Class({
constructor() { Name: 'SmartcardManager',
_init() {
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;
} },
_onLoaded() { _onLoaded() {
let tokens = this._objectManager.getProxiesForInterface('org.gnome.SettingsDaemon.Smartcard.Token'); let tokens = this._objectManager.getProxiesForInterface('org.gnome.SettingsDaemon.Smartcard.Token');
@@ -50,7 +53,7 @@ var SmartcardManager = class {
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token') if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
this._removeToken(proxy); this._removeToken(proxy);
}); });
} },
_updateToken(token) { _updateToken(token) {
let objectPath = token.get_object_path(); let objectPath = token.get_object_path();
@@ -62,7 +65,7 @@ var SmartcardManager = class {
if (token.UsedToLogin) if (token.UsedToLogin)
this._loginToken = token; this._loginToken = token;
} },
_addToken(token) { _addToken(token) {
this._updateToken(token); this._updateToken(token);
@@ -82,7 +85,7 @@ var SmartcardManager = class {
// Emit a smartcard-inserted at startup if it's already plugged in // Emit a smartcard-inserted at startup if it's already plugged in
if (token.IsInserted) if (token.IsInserted)
this.emit('smartcard-inserted', token); this.emit('smartcard-inserted', token);
} },
_removeToken(token) { _removeToken(token) {
let objectPath = token.get_object_path(); let objectPath = token.get_object_path();
@@ -96,11 +99,11 @@ var SmartcardManager = class {
this._loginToken = null; this._loginToken = null;
token.disconnectAll(); token.disconnectAll();
} },
hasInsertedTokens() { hasInsertedTokens() {
return Object.keys(this._insertedTokens).length > 0; return Object.keys(this._insertedTokens).length > 0;
} },
hasInsertedLoginToken() { hasInsertedLoginToken() {
if (!this._loginToken) if (!this._loginToken)
@@ -112,5 +115,5 @@ var SmartcardManager = class {
return true; return true;
} }
}; });
Signals.addSignalMethods(SmartcardManager.prototype); Signals.addSignalMethods(SmartcardManager.prototype);

View File

@@ -1,4 +1,11 @@
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi; const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
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;
@@ -37,7 +44,9 @@ function getDefault() {
return _singleton; return _singleton;
} }
const SystemActions = GObject.registerClass({ const SystemActions = new Lang.Class({
Name: 'SystemActions',
Extends: GObject.Object,
Properties: { Properties: {
'can-power-off': GObject.ParamSpec.boolean('can-power-off', 'can-power-off': GObject.ParamSpec.boolean('can-power-off',
'can-power-off', 'can-power-off',
@@ -74,63 +83,57 @@ const SystemActions = GObject.registerClass({
'orientation-lock-icon', 'orientation-lock-icon',
GObject.ParamFlags.READWRITE, GObject.ParamFlags.READWRITE,
null) null)
} },
}, class SystemActions extends GObject.Object {
_init() { _init() {
super._init(); this.parent();
this._canHavePowerOff = true; this._canHavePowerOff = true;
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 });
@@ -143,39 +146,37 @@ 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(); });
Gio.DBus.system.watch_name(SENSOR_BUS_NAME, Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
Gio.BusNameWatcherFlags.NONE, Gio.BusNameWatcherFlags.NONE,
() => this._sensorProxyAppeared(), () => { this._sensorProxyAppeared(); },
() => { () => {
this._sensorProxy = null; this._sensorProxy = null;
this._updateOrientationLock(); this._updateOrientationLock();
@@ -183,37 +184,37 @@ const SystemActions = GObject.registerClass({
this._updateOrientationLock(); this._updateOrientationLock();
this._updateOrientationLockIcon(); this._updateOrientationLockIcon();
Main.sessionMode.connect('updated', () => this._sessionUpdated()); Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
this._sessionUpdated(); this._sessionUpdated();
} },
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;
} },
get can_suspend() { get can_suspend() {
return this._actions.get(SUSPEND_ACTION_ID).available; return this._actions.get(SUSPEND_ACTION_ID).available;
} },
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;
} },
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;
} },
get can_logout() { get can_logout() {
return this._actions.get(LOGOUT_ACTION_ID).available; return this._actions.get(LOGOUT_ACTION_ID).available;
} },
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;
} },
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() { _sensorProxyAppeared() {
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH, this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
@@ -223,10 +224,10 @@ const SystemActions = GObject.registerClass({
return; return;
} }
this._sensorProxy.connect('g-properties-changed', this._sensorProxy.connect('g-properties-changed',
() => this._updateOrientationLock()); () => { this._updateOrientationLock(); });
this._updateOrientationLock(); this._updateOrientationLock();
}); });
} },
_updateOrientationLock() { _updateOrientationLock() {
let available = false; let available = false;
@@ -237,7 +238,7 @@ const SystemActions = GObject.registerClass({
this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available; this._actions.get(LOCK_ORIENTATION_ACTION_ID).available = available;
this.notify('can-lock-orientation'); this.notify('can-lock-orientation');
} },
_updateOrientationLockIcon() { _updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock'); let locked = this._orientationSettings.get_boolean('orientation-lock');
@@ -246,14 +247,14 @@ const SystemActions = GObject.registerClass({
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName; this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
this.notify('orientation-lock-icon'); this.notify('orientation-lock-icon');
} },
_sessionUpdated() { _sessionUpdated() {
this._updateLockScreen(); this._updateLockScreen();
this._updatePowerOff(); this._updatePowerOff();
this._updateSuspend(); this._updateSuspend();
this._updateMultiUser(); this._updateMultiUser();
} },
forceUpdate() { forceUpdate() {
// Whether those actions are available or not depends on both lockdown // Whether those actions are available or not depends on both lockdown
@@ -261,28 +262,28 @@ const SystemActions = GObject.registerClass({
// latter, so their value may be outdated; force an update now // latter, so their value may be outdated; force an update now
this._updateHaveShutdown(); this._updateHaveShutdown();
this._updateHaveSuspend(); this._updateHaveSuspend();
} },
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;
} },
getName(id) { getName(id) {
return this._actions.get(id).name; return this._actions.get(id).name;
} },
getIconName(id) { getIconName(id) {
return this._actions.get(id).iconName; return this._actions.get(id).iconName;
} },
activateAction(id) { activateAction(id) {
switch (id) { switch (id) {
@@ -305,14 +306,14 @@ const SystemActions = GObject.registerClass({
this.activateLockOrientation(); this.activateLockOrientation();
break; break;
} }
} },
_updateLockScreen() { _updateLockScreen() {
let showLock = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter; let showLock = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY); let allowLockScreen = !this._lockdownSettings.get_boolean(DISABLE_LOCK_SCREEN_KEY);
this._actions.get(LOCK_SCREEN_ACTION_ID).available = showLock && allowLockScreen && LoginManager.canLock(); this._actions.get(LOCK_SCREEN_ACTION_ID).available = showLock && allowLockScreen && LoginManager.canLock();
this.notify('can-lock-screen'); this.notify('can-lock-screen');
} },
_updateHaveShutdown() { _updateHaveShutdown() {
this._session.CanShutdownRemote((result, error) => { this._session.CanShutdownRemote((result, error) => {
@@ -322,7 +323,7 @@ const SystemActions = GObject.registerClass({
this._canHavePowerOff = result[0]; this._canHavePowerOff = result[0];
this._updatePowerOff(); this._updatePowerOff();
}); });
} },
_updatePowerOff() { _updatePowerOff() {
let disabled = Main.sessionMode.isLocked || let disabled = Main.sessionMode.isLocked ||
@@ -330,7 +331,7 @@ const SystemActions = GObject.registerClass({
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY)); this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
this._actions.get(POWER_OFF_ACTION_ID).available = this._canHavePowerOff && !disabled; this._actions.get(POWER_OFF_ACTION_ID).available = this._canHavePowerOff && !disabled;
this.notify('can-power-off'); this.notify('can-power-off');
} },
_updateHaveSuspend() { _updateHaveSuspend() {
this._loginManager.canSuspend( this._loginManager.canSuspend(
@@ -339,7 +340,7 @@ const SystemActions = GObject.registerClass({
this._suspendNeedsAuth = needsAuth; this._suspendNeedsAuth = needsAuth;
this._updateSuspend(); this._updateSuspend();
}); });
} },
_updateSuspend() { _updateSuspend() {
let disabled = (Main.sessionMode.isLocked && let disabled = (Main.sessionMode.isLocked &&
@@ -348,12 +349,12 @@ const SystemActions = GObject.registerClass({
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY)); this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
this._actions.get(SUSPEND_ACTION_ID).available = this._canHaveSuspend && !disabled; this._actions.get(SUSPEND_ACTION_ID).available = this._canHaveSuspend && !disabled;
this.notify('can-suspend'); this.notify('can-suspend');
} },
_updateMultiUser() { _updateMultiUser() {
this._updateLogout(); this._updateLogout();
this._updateSwitchUser(); this._updateSwitchUser();
} },
_updateSwitchUser() { _updateSwitchUser() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY); let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
@@ -365,7 +366,7 @@ const SystemActions = GObject.registerClass({
this.notify('can-switch-user'); this.notify('can-switch-user');
return visible; return visible;
} },
_updateLogout() { _updateLogout() {
let user = this._userManager.get_user(GLib.get_user_name()); let user = this._userManager.get_user(GLib.get_user_name());
@@ -383,7 +384,7 @@ const SystemActions = GObject.registerClass({
this.notify('can-logout'); this.notify('can-logout');
return visible; return visible;
} },
activateLockOrientation() { activateLockOrientation() {
if (!this._actions.get(LOCK_ORIENTATION_ACTION_ID).available) if (!this._actions.get(LOCK_ORIENTATION_ACTION_ID).available)
@@ -391,14 +392,14 @@ const SystemActions = GObject.registerClass({
let locked = this._orientationSettings.get_boolean('orientation-lock'); let locked = this._orientationSettings.get_boolean('orientation-lock');
this._orientationSettings.set_boolean('orientation-lock', !locked); this._orientationSettings.set_boolean('orientation-lock', !locked);
} },
activateLockScreen() { activateLockScreen() {
if (!this._actions.get(LOCK_SCREEN_ACTION_ID).available) if (!this._actions.get(LOCK_SCREEN_ACTION_ID).available)
throw new Error('The lock-screen action is not available!'); throw new Error('The lock-screen action is not available!');
Main.screenShield.lock(true); Main.screenShield.lock(true);
} },
activateSwitchUser() { activateSwitchUser() {
if (!this._actions.get(SWITCH_USER_ACTION_ID).available) if (!this._actions.get(SWITCH_USER_ACTION_ID).available)
@@ -411,7 +412,7 @@ const SystemActions = GObject.registerClass({
Gdm.goto_login_session_sync(null); Gdm.goto_login_session_sync(null);
return false; return false;
}); });
} },
activateLogout() { activateLogout() {
if (!this._actions.get(LOGOUT_ACTION_ID).available) if (!this._actions.get(LOGOUT_ACTION_ID).available)
@@ -419,14 +420,14 @@ const SystemActions = GObject.registerClass({
Main.overview.hide(); Main.overview.hide();
this._session.LogoutRemote(0); this._session.LogoutRemote(0);
} },
activatePowerOff() { activatePowerOff() {
if (!this._actions.get(POWER_OFF_ACTION_ID).available) if (!this._actions.get(POWER_OFF_ACTION_ID).available)
throw new Error('The power-off action is not available!'); throw new Error('The power-off action is not available!');
this._session.ShutdownRemote(0); this._session.ShutdownRemote(0);
} },
activateSuspend() { activateSuspend() {
if (!this._actions.get(SUSPEND_ACTION_ID).available) if (!this._actions.get(SUSPEND_ACTION_ID).available)

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 -*-
const { Clutter, Gio, GLib, GObject, Shell, St } = 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 Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Signals = imports.signals; 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 Tweener = imports.ui.tweener;
@@ -17,7 +22,7 @@ const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]'; 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,7 +108,8 @@ 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,
@@ -134,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;
} }
@@ -221,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
@@ -250,7 +256,7 @@ function formatTime(time, params) {
/* 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
@@ -288,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;
} }
@@ -342,10 +348,12 @@ function insertSorted(array, val, cmp) {
return pos; return pos;
} }
var CloseButton = GObject.registerClass( var CloseButton = new Lang.Class({
class CloseButton extends St.Button { Name: 'CloseButton',
Extends: St.Button,
_init(boxpointer) { _init(boxpointer) {
super._init({ style_class: 'notification-close' }); this.parent({ style_class: 'notification-close'});
// This is a bit tricky. St.Bin has its own x-align/y-align properties // This is a bit tricky. St.Bin has its own x-align/y-align properties
// that compete with Clutter's properties. This should be fixed for // that compete with Clutter's properties. This should be fixed for
@@ -362,10 +370,10 @@ class CloseButton extends St.Button {
this._boxPointer = boxpointer; this._boxPointer = boxpointer;
if (boxpointer) if (boxpointer)
this._boxPointer.connect('arrow-side-changed', this._sync.bind(this)); this._boxPointer.connect('arrow-side-changed', this._sync.bind(this));
} },
_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;
@@ -373,20 +381,20 @@ class CloseButton extends St.Button {
return this._boxPointer.getArrowHeight(); return this._boxPointer.getArrowHeight();
else else
return 0; return 0;
} },
_sync() { _sync() {
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;
} },
vfunc_style_changed() { vfunc_style_changed() {
this._sync(); this._sync();
super.vfunc_style_changed(); this.parent();
} },
}); });
function makeCloseButton(boxpointer) { function makeCloseButton(boxpointer) {
@@ -429,8 +437,10 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
} }
var AppSettingsMonitor = class { var AppSettingsMonitor = new Lang.Class({
constructor(appId, schemaId) { Name: 'AppSettingsMonitor',
_init(appId, schemaId) {
this._appId = appId; this._appId = appId;
this._schemaId = schemaId; this._schemaId = schemaId;
@@ -444,38 +454,38 @@ var AppSettingsMonitor = class {
this._appSystem.connect('installed-changed', this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this)); this._onInstalledChanged.bind(this));
this._onInstalledChanged(); this._onInstalledChanged();
} },
get available() { get available() {
return this._app != null && this._settings != null; return this._app != null && this._settings != null;
} },
activateApp() { activateApp() {
if (this._app) if (this._app)
this._app.activate(); this._app.activate();
} },
watchSetting(key, callback) { watchSetting(key, callback) {
let handler = { id: 0, key: key, callback: callback }; let handler = { id: 0, key: key, callback: callback };
this._handlers.push(handler); this._handlers.push(handler);
this._connectHandler(handler); this._connectHandler(handler);
} },
_connectHandler(handler) { _connectHandler(handler) {
if (!this._settings || handler.id > 0) if (!this._settings || handler.id > 0)
return; return;
handler.id = this._settings.connect(`changed::${handler.key}`, handler.id = this._settings.connect('changed::' + handler.key,
handler.callback); handler.callback);
handler.callback(this._settings, handler.key); handler.callback(this._settings, handler.key);
} },
_disconnectHandler(handler) { _disconnectHandler(handler) {
if (this._settings && handler.id > 0) if (this._settings && handler.id > 0)
this._settings.disconnect(handler.id); this._settings.disconnect(handler.id);
handler.id = 0; handler.id = 0;
} },
_onInstalledChanged() { _onInstalledChanged() {
let hadApp = (this._app != null); let hadApp = (this._app != null);
@@ -489,20 +499,20 @@ var AppSettingsMonitor = class {
this._checkSettings(); this._checkSettings();
else else
this._setSettings(null); this._setSettings(null);
} },
_setSettings(settings) { _setSettings(settings) {
this._handlers.forEach((handler) => this._disconnectHandler(handler)); this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
let hadSettings = (this._settings != null); let hadSettings = (this._settings != null);
this._settings = settings; this._settings = settings;
let haveSettings = (this._settings != null); let haveSettings = (this._settings != null);
this._handlers.forEach((handler) => this._connectHandler(handler)); this._handlers.forEach((handler) => { this._connectHandler(handler); });
if (hadSettings != haveSettings) if (hadSettings != haveSettings)
this.emit('available-changed'); this.emit('available-changed');
} },
_checkSettings() { _checkSettings() {
let schema = this._schemaSource.lookup(this._schemaId, true); let schema = this._schemaSource.lookup(this._schemaId, true);
@@ -515,5 +525,5 @@ var AppSettingsMonitor = class {
}); });
} }
} }
}; });
Signals.addSignalMethods(AppSettingsMonitor.prototype); Signals.addSignalMethods(AppSettingsMonitor.prototype);

View File

@@ -1,6 +1,10 @@
// -*- 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 } = imports.gi; const Geoclue = imports.gi.Geoclue;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GWeather = imports.gi.GWeather;
const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore; const PermissionStore = imports.misc.permissionStore;
@@ -9,8 +13,10 @@ const Util = imports.misc.util;
// 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;
var WeatherClient = class { var WeatherClient = new Lang.Class({
constructor() { Name: 'WeatherClient',
_init() {
this._loading = false; this._loading = false;
this._locationValid = false; this._locationValid = false;
this._lastUpdate = GLib.DateTime.new_from_unix_local(0); this._lastUpdate = GLib.DateTime.new_from_unix_local(0);
@@ -26,21 +32,13 @@ var WeatherClient = class {
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;
}
if (this._permStore.g_name_owner == null) {
// Failed to auto-start, likely because xdg-desktop-portal
// isn't installed; don't restrict access to location service
this._weatherAuthorized = true;
this._updateAutoLocation();
return; return;
} }
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => { this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (error) if (error)
log(`Error looking up permission: ${error.message}`); log('Error looking up permission: ' + error.message);
let [perms, data] = error ? [{}, null] : res; let [perms, data] = error ? [{}, null] : res;
let params = ['gnome', 'geolocation', false, data, perms]; let params = ['gnome', 'geolocation', false, data, perms];
@@ -66,34 +64,34 @@ var WeatherClient = class {
this.emit('changed'); this.emit('changed');
}); });
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop', this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
'org.gnome.Weather'); 'org.gnome.Weather.Application');
this._weatherAppMon.connect('available-changed', () => this.emit('changed')); this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
this._weatherAppMon.watchSetting('automatic-location', this._weatherAppMon.watchSetting('automatic-location',
this._onAutomaticLocationChanged.bind(this)); this._onAutomaticLocationChanged.bind(this));
this._weatherAppMon.watchSetting('locations', this._weatherAppMon.watchSetting('locations',
this._onLocationsChanged.bind(this)); this._onLocationsChanged.bind(this));
} },
get available() { get available() {
return this._weatherAppMon.available; return this._weatherAppMon.available;
} },
get loading() { get loading() {
return this._loading; return this._loading;
} },
get hasLocation() { get hasLocation() {
return this._locationValid; return this._locationValid;
} },
get info() { get info() {
return this._weatherInfo; return this._weatherInfo;
} },
activateApp() { activateApp() {
this._weatherAppMon.activateApp(); this._weatherAppMon.activateApp();
} },
update() { update() {
if (!this._locationValid) if (!this._locationValid)
@@ -106,13 +104,13 @@ var WeatherClient = class {
this._weatherInfo.update(); this._weatherInfo.update();
else else
this._loadInfo(); this._loadInfo();
} },
get _useAutoLocation() { get _useAutoLocation() {
return this._autoLocationRequested && return this._autoLocationRequested &&
this._locationSettings.get_boolean('enabled') && this._locationSettings.get_boolean('enabled') &&
this._weatherAuthorized; this._weatherAuthorized;
} },
_loadInfo() { _loadInfo() {
let id = this._weatherInfo.connect('updated', () => { let id = this._weatherInfo.connect('updated', () => {
@@ -124,7 +122,7 @@ var WeatherClient = class {
this.emit('changed'); this.emit('changed');
this._weatherInfo.update(); this._weatherInfo.update();
} },
_locationsEqual(loc1, loc2) { _locationsEqual(loc1, loc2) {
if (loc1 == loc2) if (loc1 == loc2)
@@ -134,7 +132,7 @@ var WeatherClient = class {
return false; return false;
return loc1.equal(loc2); return loc1.equal(loc2);
} },
_setLocation(location) { _setLocation(location) {
if (this._locationsEqual(this._weatherInfo.location, location)) if (this._locationsEqual(this._weatherInfo.location, location))
@@ -150,7 +148,7 @@ var WeatherClient = class {
this._loadInfo(); this._loadInfo();
else else
this.emit('changed'); this.emit('changed');
} },
_updateLocationMonitoring() { _updateLocationMonitoring() {
if (this._useAutoLocation) { if (this._useAutoLocation) {
@@ -166,7 +164,7 @@ var WeatherClient = class {
this._gclueService.disconnect(this._gclueLocationChangedId); this._gclueService.disconnect(this._gclueLocationChangedId);
this._gclueLocationChangedId = 0; this._gclueLocationChangedId = 0;
} }
} },
_startGClueService() { _startGClueService() {
if (this._gclueStarting) if (this._gclueStarting)
@@ -178,8 +176,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;
} }
@@ -187,7 +185,7 @@ var WeatherClient = class {
this._gclueService.get_client().distance_threshold = 100; this._gclueService.get_client().distance_threshold = 100;
this._updateLocationMonitoring(); this._updateLocationMonitoring();
}); });
} },
_onGClueLocationChanged() { _onGClueLocationChanged() {
let geoLocation = this._gclueService.location; let geoLocation = this._gclueService.location;
@@ -196,7 +194,7 @@ var WeatherClient = class {
geoLocation.latitude, geoLocation.latitude,
geoLocation.longitude); geoLocation.longitude);
this._setLocation(location); this._setLocation(location);
} },
_onAutomaticLocationChanged(settings, key) { _onAutomaticLocationChanged(settings, key) {
let useAutoLocation = settings.get_boolean(key); let useAutoLocation = settings.get_boolean(key);
@@ -206,7 +204,7 @@ var WeatherClient = class {
this._autoLocationRequested = useAutoLocation; this._autoLocationRequested = useAutoLocation;
this._updateAutoLocation(); this._updateAutoLocation();
} },
_updateAutoLocation() { _updateAutoLocation() {
this._updateLocationMonitoring(); this._updateLocationMonitoring();
@@ -215,7 +213,7 @@ var WeatherClient = class {
this._startGClueService(); this._startGClueService();
else else
this._setLocation(this._mostRecentLocation); this._setLocation(this._mostRecentLocation);
} },
_onLocationsChanged(settings, key) { _onLocationsChanged(settings, key) {
let serialized = settings.get_value(key).deep_unpack().shift(); let serialized = settings.get_value(key).deep_unpack().shift();
@@ -231,7 +229,7 @@ var WeatherClient = class {
if (!this._useAutoLocation || !this._gclueStarted) if (!this._useAutoLocation || !this._gclueStarted)
this._setLocation(this._mostRecentLocation); this._setLocation(this._mostRecentLocation);
} },
_onPermStoreChanged(proxy, sender, params) { _onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted, data, perms] = params; let [table, id, deleted, data, perms] = params;
@@ -239,11 +237,11 @@ var WeatherClient = class {
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';
this._updateAutoLocation(); this._updateAutoLocation();
} }
}; });
Signals.addSignalMethods(WeatherClient.prototype); Signals.addSignalMethods(WeatherClient.prototype);

View File

@@ -10,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" },
@@ -19,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" },
@@ -52,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 = [
@@ -65,7 +65,7 @@ let WINDOW_CONFIGS = [
{ 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");
@@ -136,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;

View File

@@ -1,8 +1,12 @@
const { Clutter, Gio, Shell } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
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" },
@@ -30,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;
@@ -48,7 +52,7 @@ function waitAndDraw(milliseconds) {
cb(); cb();
}); });
return callback => cb = callback; return callback => { cb = callback; };
} }
function waitSignal(object, signal) { function waitSignal(object, signal) {
@@ -60,7 +64,7 @@ function waitSignal(object, signal) {
cb(); cb();
}); });
return callback => cb = callback; return callback => { cb = callback; };
} }
function extractBootTimestamp() { function extractBootTimestamp() {
@@ -85,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");
@@ -104,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();
@@ -157,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);
@@ -203,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;
@@ -269,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,6 +1,13 @@
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 Lang = imports.lang;
const Pango = imports.gi.Pango;
const Soup = imports.gi.Soup;
const WebKit = imports.gi.WebKit2;
const _ = Gettext.gettext; const _ = Gettext.gettext;
@@ -19,16 +26,19 @@ const PortalHelperSecurityLevel = {
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');
var PortalHeaderBar = GObject.registerClass( var PortalHeaderBar = new Lang.Class({
class PortalHeaderBar extends Gtk.HeaderBar { Name: 'PortalHeaderBar',
Extends: Gtk.HeaderBar,
_init() { _init() {
super._init({ show_close_button: true }); this.parent({ show_close_button: true });
// See ephy-title-box.c in epiphany for the layout // See ephy-title-box.c in epiphany for the layout
let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
@@ -58,16 +68,16 @@ 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);
vbox.show_all(); vbox.show_all();
} },
setSubtitle(label) { setSubtitle(label) {
this.subtitleLabel.set_text(label); this.subtitleLabel.set_text(label);
} },
setSecurityIcon(securityLevel) { setSecurityIcon(securityLevel) {
switch (securityLevel) { switch (securityLevel) {
@@ -85,13 +95,15 @@ class PortalHeaderBar extends Gtk.HeaderBar {
this._lockImage.set_tooltip_text(_('Your connection to this hotspot login is not secure. Passwords or other information you enter on this page can be viewed by people nearby.')); this._lockImage.set_tooltip_text(_('Your connection to this hotspot login is not secure. Passwords or other information you enter on this page can be viewed by people nearby.'));
break; break;
} }
} },
}); });
var PortalWindow = GObject.registerClass( var PortalWindow = new Lang.Class({
class PortalWindow extends Gtk.ApplicationWindow { Name: 'PortalWindow',
Extends: Gtk.ApplicationWindow,
_init(application, url, timestamp, doneCallback) { _init(application, url, timestamp, doneCallback) {
super._init({ application: application }); this.parent({ 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();
@@ -132,11 +144,11 @@ class PortalWindow extends Gtk.ApplicationWindow {
this.present_with_time(timestamp); this.present_with_time(timestamp);
this.application.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w']); this.application.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w']);
} },
destroyWindow() { destroyWindow() {
this.destroy(); this.destroy();
} },
_syncUri() { _syncUri() {
let uri = this._webView.uri; let uri = this._webView.uri;
@@ -144,12 +156,12 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._headerBar.setSubtitle(GLib.uri_unescape_string(uri, null)); this._headerBar.setSubtitle(GLib.uri_unescape_string(uri, null));
else else
this._headerBar.setSubtitle(''); this._headerBar.setSubtitle('');
} },
refresh() { refresh() {
this._everSeenRedirect = false; this._everSeenRedirect = false;
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)
@@ -157,7 +169,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
else else
this._doneCallback(PortalHelperResult.CANCELLED); this._doneCallback(PortalHelperResult.CANCELLED);
return false; return false;
} },
_onLoadChanged(view, loadEvent) { _onLoadChanged(view, loadEvent) {
if (loadEvent == WebKit.LoadEvent.STARTED) { if (loadEvent == WebKit.LoadEvent.STARTED) {
@@ -171,11 +183,11 @@ class PortalWindow extends Gtk.ApplicationWindow {
else else
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE); this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
} }
} },
_onInsecureContentDetected() { _onInsecureContentDetected() {
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);
@@ -183,7 +195,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host()); this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
this._webView.load_uri(failingURI); this._webView.load_uri(failingURI);
return true; return true;
} },
_onDecidePolicy(view, decision, type) { _onDecidePolicy(view, decision, type) {
if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) { if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
@@ -250,13 +262,15 @@ class PortalWindow extends Gtk.ApplicationWindow {
decision.use(); decision.use();
return true; return true;
} },
}); });
var WebPortalHelper = GObject.registerClass( var WebPortalHelper = new Lang.Class({
class WebPortalHelper extends Gtk.Application { Name: 'WebPortalHelper',
Extends: Gtk.Application,
_init() { _init() {
super._init({ application_id: 'org.gnome.Shell.PortalHelper', this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
flags: Gio.ApplicationFlags.IS_SERVICE, flags: Gio.ApplicationFlags.IS_SERVICE,
inactivity_timeout: 30000 }); inactivity_timeout: 30000 });
@@ -264,32 +278,32 @@ 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);
} },
vfunc_dbus_register(connection, path) { vfunc_dbus_register(connection, path) {
this._dbusImpl.export(connection, path); this._dbusImpl.export(connection, path);
super.vfunc_dbus_register(connection, path); this.parent(connection, path);
return true; return true;
} },
vfunc_dbus_unregister(connection, path) { vfunc_dbus_unregister(connection, path) {
this._dbusImpl.unexport_from_connection(connection); this._dbusImpl.unexport_from_connection(connection);
super.vfunc_dbus_unregister(connection, path); this.parent(connection, path);
} },
vfunc_activate() { vfunc_activate() {
// If launched manually (for example for testing), force a dummy authentication // If launched manually (for example for testing), force a dummy authentication
// session with the default url // session with the default url
this.Authenticate('/org/gnome/dummy', '', 0); this.Authenticate('/org/gnome/dummy', '', 0);
} },
Authenticate(connection, url, timestamp) { Authenticate(connection, url, timestamp) {
this._queue.push({ connection: connection, url: url, timestamp: timestamp }); this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue(); this._processQueue();
} },
Close(connection) { Close(connection) {
for (let i = 0; i < this._queue.length; i++) { for (let i = 0; i < this._queue.length; i++) {
@@ -304,7 +318,7 @@ class WebPortalHelper extends Gtk.Application {
} }
this._processQueue(); this._processQueue();
} },
Refresh(connection) { Refresh(connection) {
for (let i = 0; i < this._queue.length; i++) { for (let i = 0; i < this._queue.length; i++) {
@@ -316,7 +330,7 @@ class WebPortalHelper extends Gtk.Application {
break; break;
} }
} }
} },
_processQueue() { _processQueue() {
if (this._queue.length == 0) if (this._queue.length == 0)
@@ -329,7 +343,7 @@ class WebPortalHelper extends Gtk.Application {
top.window = new PortalWindow(this, top.url, top.timestamp, result => { top.window = new PortalWindow(this, top.url, top.timestamp, result => {
this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result])); this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
}); });
} },
}); });
function initEnvironment() { function initEnvironment() {

View File

@@ -1,4 +1,10 @@
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
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;
@@ -15,10 +21,12 @@ var DialogResponse = {
CLOSED: 2 CLOSED: 2
}; };
var AccessDialog = GObject.registerClass( var AccessDialog = new Lang.Class({
class AccessDialog extends ModalDialog.ModalDialog { Name: 'AccessDialog',
Extends: ModalDialog.ModalDialog,
_init(invocation, handle, title, subtitle, body, options) { _init(invocation, handle, title, subtitle, body, options) {
super._init({ styleClass: 'access-dialog' }); this.parent({ styleClass: 'access-dialog' });
this._invocation = invocation; this._invocation = invocation;
this._handle = handle; this._handle = handle;
@@ -30,7 +38,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
options[option] = options[option].deep_unpack(); options[option] = options[option].deep_unpack();
this._buildLayout(title, subtitle, body, options); this._buildLayout(title, subtitle, body, options);
} },
_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
@@ -69,15 +77,15 @@ 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() {
super.open(); this.parent();
let connection = this._invocation.get_connection(); let connection = this._invocation.get_connection();
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()) {
@@ -88,7 +96,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
} }
this._sendResponse(DialogResponse.CLOSED); this._sendResponse(DialogResponse.CLOSED);
} },
_sendResponse(response) { _sendResponse(response) {
if (this._requestExported) if (this._requestExported)
@@ -112,8 +120,10 @@ class AccessDialog extends ModalDialog.ModalDialog {
} }
}); });
var AccessDialogDBus = class { var AccessDialogDBus = new Lang.Class({
constructor() { Name: 'AccessDialogDBus',
_init() {
this._accessDialog = null; this._accessDialog = null;
this._windowTracker = Shell.WindowTracker.get_default(); this._windowTracker = Shell.WindowTracker.get_default();
@@ -122,7 +132,7 @@ var AccessDialogDBus = class {
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/portal/desktop'); this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/portal/desktop');
Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null); Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null);
} },
AccessDialogAsync(params, invocation) { AccessDialogAsync(params, invocation) {
if (this._accessDialog) { if (this._accessDialog) {
@@ -135,7 +145,7 @@ var AccessDialogDBus = class {
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');
@@ -146,8 +156,8 @@ 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,7 +1,15 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
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 Lang = imports.lang;
const Mainloop = imports.mainloop; 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;
@@ -36,7 +44,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
@@ -51,10 +59,12 @@ function getWindows(workspace) {
}).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i); }).filter((w, i, a) => !w.skip_taskbar && a.indexOf(w) == i);
} }
var AppSwitcherPopup = GObject.registerClass( var AppSwitcherPopup = new Lang.Class({
class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup { Name: 'AppSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init() { _init() {
super._init(); this.parent();
this._thumbnails = null; this._thumbnails = null;
this._thumbnailTimeoutId = 0; this._thumbnailTimeoutId = 0;
@@ -69,10 +79,10 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._switcherList = new AppSwitcher(apps, this); this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons; this._items = this._switcherList.icons;
} },
vfunc_allocate(box, flags) { vfunc_allocate(box, flags) {
super.vfunc_allocate(box, flags); this.parent(box, flags);
// Allocate the thumbnails // Allocate the thumbnails
// We try to avoid overflowing the screen so we base the resulting size on // We try to avoid overflowing the screen so we base the resulting size on
@@ -107,7 +117,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
childBox.y2 = childBox.y1 + childNaturalHeight; childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags); this._thumbnails.allocate(childBox, flags);
} }
} },
_initialSelection(backward, binding) { _initialSelection(backward, binding) {
if (binding == 'switch-group') { if (binding == 'switch-group') {
@@ -130,7 +140,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} else { } else {
this._select(1); this._select(1);
} }
} },
_nextWindow() { _nextWindow() {
// We actually want the second window if we're in the unset state // We actually want the second window if we're in the unset state
@@ -138,15 +148,14 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._currentWindow = 0; this._currentWindow = 0;
return SwitcherPopup.mod(this._currentWindow + 1, return SwitcherPopup.mod(this._currentWindow + 1,
this._items[this._selectedIndex].cachedWindows.length); this._items[this._selectedIndex].cachedWindows.length);
} },
_previousWindow() { _previousWindow() {
// Also assume second window here // Also assume second window here
if (this._currentWindow == -1) if (this._currentWindow == -1)
this._currentWindow = 1; this._currentWindow = 1;
return SwitcherPopup.mod(this._currentWindow - 1, return SwitcherPopup.mod(this._currentWindow - 1,
this._items[this._selectedIndex].cachedWindows.length); this._items[this._selectedIndex].cachedWindows.length);
} },
_closeAppWindow(appIndex, windowIndex) { _closeAppWindow(appIndex, windowIndex) {
let appIcon = this._items[appIndex]; let appIcon = this._items[appIndex];
@@ -158,7 +167,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
return; return;
window.delete(global.get_current_time()); window.delete(global.get_current_time());
} },
_quitApplication(appIndex) { _quitApplication(appIndex) {
let appIcon = this._items[appIndex]; let appIcon = this._items[appIndex];
@@ -166,7 +175,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
return; return;
appIcon.app.request_quit(); appIcon.app.request_quit();
} },
_keyPressHandler(keysym, action) { _keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) { if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
@@ -205,7 +214,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} },
_scrollHandler(direction) { _scrollHandler(direction) {
if (direction == Clutter.ScrollDirection.UP) { if (direction == Clutter.ScrollDirection.UP) {
@@ -235,7 +244,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._select(this._next()); this._select(this._next());
} }
} }
} },
_itemActivatedHandler(n) { _itemActivatedHandler(n) {
// If the user clicks on the selected app, activate the // If the user clicks on the selected app, activate the
@@ -245,24 +254,24 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._select(n, this._currentWindow); this._select(n, this._currentWindow);
else else
this._select(n); this._select(n);
} },
_itemEnteredHandler(n) { _itemEnteredHandler(n) {
this._select(n); this._select(n);
} },
_windowActivated(thumbnailList, n) { _windowActivated(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex]; let appIcon = this._items[this._selectedIndex];
Main.activateWindow(appIcon.cachedWindows[n]); Main.activateWindow(appIcon.cachedWindows[n]);
this.fadeAndDestroy(); this.fadeAndDestroy();
} },
_windowEntered(thumbnailList, n) { _windowEntered(thumbnailList, n) {
if (!this.mouseActive) if (!this.mouseActive)
return; return;
this._select(this._selectedIndex, n); this._select(this._selectedIndex, n);
} },
_windowRemoved(thumbnailList, n) { _windowRemoved(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex]; let appIcon = this._items[this._selectedIndex];
@@ -273,7 +282,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
let newIndex = Math.min(n, appIcon.cachedWindows.length - 1); let newIndex = Math.min(n, appIcon.cachedWindows.length - 1);
this._select(this._selectedIndex, newIndex); this._select(this._selectedIndex, newIndex);
} }
} },
_finish(timestamp) { _finish(timestamp) {
let appIcon = this._items[this._selectedIndex]; let appIcon = this._items[this._selectedIndex];
@@ -282,17 +291,17 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
else if (appIcon.cachedWindows[this._currentWindow]) else if (appIcon.cachedWindows[this._currentWindow])
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp); Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
super._finish(timestamp); this.parent();
} },
_onDestroy() { _onDestroy() {
super._onDestroy(); this.parent();
if (this._thumbnails) if (this._thumbnails)
this._destroyThumbnails(); this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0) if (this._thumbnailTimeoutId != 0)
Mainloop.source_remove(this._thumbnailTimeoutId); Mainloop.source_remove(this._thumbnailTimeoutId);
} },
/** /**
* _select: * _select:
@@ -348,7 +357,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
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');
} }
} },
_timeoutPopupThumbnails() { _timeoutPopupThumbnails() {
if (!this._thumbnails) if (!this._thumbnails)
@@ -356,7 +365,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnailTimeoutId = 0; this._thumbnailTimeoutId = 0;
this._thumbnailsFocused = false; this._thumbnailsFocused = false;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} },
_destroyThumbnails() { _destroyThumbnails() {
let thumbnailsActor = this._thumbnails; let thumbnailsActor = this._thumbnails;
@@ -372,7 +381,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
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);
@@ -395,15 +404,17 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
{ opacity: 255, { opacity: 255,
time: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: () => this.thumbnailsVisible = true onComplete: () => { 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);
} }
}); });
class CyclerHighlight { var CyclerHighlight = new Lang.Class({
constructor() { Name: 'CyclerHighlight',
_init() {
this._window = null; this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() }); this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
@@ -423,7 +434,7 @@ class CyclerHighlight {
this.actor.connect('notify::allocation', this.actor.connect('notify::allocation',
this._onAllocationChanged.bind(this)); this._onAllocationChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this)); this.actor.connect('destroy', this._onDestroy.bind(this));
} },
set window(w) { set window(w) {
if (this._window == w) if (this._window == w)
@@ -441,7 +452,7 @@ class CyclerHighlight {
windowActor.hide(); windowActor.hide();
this._clone.source = windowActor; this._clone.source = windowActor;
} },
_onAllocationChanged() { _onAllocationChanged() {
if (!this._window) { if (!this._window) {
@@ -454,31 +465,35 @@ class CyclerHighlight {
this._highlight.set_position(rect.x - x, rect.y - y); this._highlight.set_position(rect.x - x, rect.y - y);
this._highlight.show(); this._highlight.show();
} }
} },
_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
var CyclerList = GObject.registerClass({ var CyclerList = new Lang.Class({
Name: 'CyclerList',
Extends: St.Widget,
Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] }, Signals: { 'item-activated': { param_types: [GObject.TYPE_INT] },
'item-entered': { param_types: [GObject.TYPE_INT] }, 'item-entered': { param_types: [GObject.TYPE_INT] },
'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 {
highlight(index, justOutline) { highlight(index, justOutline) {
this.emit('item-highlighted', index); this.emit('item-highlighted', index);
} }
}); });
var CyclerPopup = GObject.registerClass({ var CyclerPopup = new Lang.Class({
GTypeFlags: GObject.TypeFlags.ABSTRACT Name: 'CyclerPopup',
}, class CyclerPopup extends SwitcherPopup.SwitcherPopup { Extends: SwitcherPopup.SwitcherPopup,
Abstract: true,
_init() { _init() {
super._init(); this.parent();
this._items = this._getWindows(); this._items = this._getWindows();
@@ -492,12 +507,12 @@ var CyclerPopup = GObject.registerClass({
this._switcherList.connect('item-highlighted', (list, index) => { this._switcherList.connect('item-highlighted', (list, index) => {
this._highlightItem(index); this._highlightItem(index);
}); });
} },
_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.actor, null); global.window_group.set_child_above_sibling(this._highlight.actor, null);
} },
_finish() { _finish() {
let window = this._items[this._selectedIndex]; let window = this._items[this._selectedIndex];
@@ -522,23 +537,25 @@ var CyclerPopup = GObject.registerClass({
Main.wm.actionMoveWindow(window, ws); Main.wm.actionMoveWindow(window, ws);
} }
super._finish(); this.parent();
} },
_onDestroy() { _onDestroy() {
this._highlight.actor.destroy(); this._highlight.actor.destroy();
super._onDestroy(); this.parent();
} }
}); });
var GroupCyclerPopup = GObject.registerClass( var GroupCyclerPopup = new Lang.Class({
class GroupCyclerPopup extends CyclerPopup { Name: 'GroupCyclerPopup',
Extends: CyclerPopup,
_getWindows() { _getWindows() {
let app = Shell.WindowTracker.get_default().focus_app; let app = Shell.WindowTracker.get_default().focus_app;
return app ? app.get_windows() : []; return app ? app.get_windows() : [];
} },
_keyPressHandler(keysym, action) { _keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_GROUP) if (action == Meta.KeyBindingAction.CYCLE_GROUP)
@@ -552,10 +569,12 @@ class GroupCyclerPopup extends CyclerPopup {
} }
}); });
var WindowSwitcherPopup = GObject.registerClass( var WindowSwitcherPopup = new Lang.Class({
class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup { Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init() { _init() {
super._init(); this.parent();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' }); this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
let windows = this._getWindowList(); let windows = this._getWindowList();
@@ -566,7 +585,7 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
let mode = this._settings.get_enum('app-icon-mode'); let mode = this._settings.get_enum('app-icon-mode');
this._switcherList = new WindowList(windows, mode); this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons; this._items = this._switcherList.icons;
} },
_getWindowList() { _getWindowList() {
let workspace = null; let workspace = null;
@@ -578,7 +597,7 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
return getWindows(workspace); return getWindows(workspace);
} },
_closeWindow(windowIndex) { _closeWindow(windowIndex) {
let windowIcon = this._items[windowIndex]; let windowIcon = this._items[windowIndex];
@@ -586,7 +605,7 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
return; return;
windowIcon.window.delete(global.get_current_time()); windowIcon.window.delete(global.get_current_time());
} },
_keyPressHandler(keysym, action) { _keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) { if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
@@ -605,21 +624,23 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} },
_finish() { _finish() {
Main.activateWindow(this._items[this._selectedIndex].window); Main.activateWindow(this._items[this._selectedIndex].window);
super._finish(); this.parent();
} }
}); });
var WindowCyclerPopup = GObject.registerClass( var WindowCyclerPopup = new Lang.Class({
class WindowCyclerPopup extends CyclerPopup { Name: 'WindowCyclerPopup',
Extends: CyclerPopup,
_init() { _init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' }); this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
super._init(); this.parent();
} },
_getWindows() { _getWindows() {
let workspace = null; let workspace = null;
@@ -631,7 +652,7 @@ class WindowCyclerPopup extends CyclerPopup {
} }
return getWindows(workspace); return getWindows(workspace);
} },
_keyPressHandler(keysym, action) { _keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_WINDOWS) if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
@@ -645,10 +666,12 @@ class WindowCyclerPopup extends CyclerPopup {
} }
}); });
var AppIcon = GObject.registerClass( var AppIcon = new Lang.Class({
class AppIcon extends St.BoxLayout { Name: 'AppIcon',
Extends: St.BoxLayout,
_init(app) { _init(app) {
super._init({ style_class: 'alt-tab-app', this.parent({ style_class: 'alt-tab-app',
vertical: true }); vertical: true });
this.app = app; this.app = app;
@@ -658,18 +681,28 @@ class AppIcon extends St.BoxLayout {
this.add(this._iconBin, { x_fill: false, y_fill: false } ); this.add(this._iconBin, { x_fill: false, y_fill: false } );
this.label = new St.Label({ text: this.app.get_name() }); this.label = new St.Label({ text: this.app.get_name() });
this.add(this.label, { x_fill: false }); this.add(this.label, { x_fill: false });
} },
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, ] = this.parent(forHeight);
minWidth = Math.max(minWidth, forHeight);
return [minWidth, minWidth];
} }
}); });
var AppSwitcher = GObject.registerClass( var AppSwitcher = new Lang.Class({
class AppSwitcher extends SwitcherPopup.SwitcherList { Name: 'AppSwitcher',
Extends: SwitcherPopup.SwitcherList,
_init(apps, altTabPopup) { _init(apps, altTabPopup) {
super._init(true); this.parent(true);
this.icons = []; this.icons = [];
this._arrows = []; this._arrows = [];
@@ -703,7 +736,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._mouseTimeOutId = 0; this._mouseTimeOutId = 0;
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} },
_onDestroy() { _onDestroy() {
if (this._mouseTimeOutId != 0) if (this._mouseTimeOutId != 0)
@@ -712,20 +745,19 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this.icons.forEach(icon => { this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId); icon.app.disconnect(icon._stateChangedId);
}); });
} },
_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
@@ -738,7 +770,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;
@@ -749,21 +781,21 @@ 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);
} }
} },
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(forWidth) {
this._setIconSize(); this._setIconSize();
return super.vfunc_get_preferred_height(forWidth); return this.parent(forWidth);
} },
vfunc_allocate(box, flags) { vfunc_allocate(box, flags) {
// Allocate the main list items // Allocate the main list items
super.vfunc_allocate(box, flags); this.parent(box, flags);
let contentBox = this.get_theme_node().get_content_box(box); let contentBox = this.get_theme_node().get_content_box(box);
@@ -780,7 +812,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
childBox.y2 = childBox.y1 + arrowHeight; childBox.y2 = childBox.y1 + arrowHeight;
this._arrows[i].allocate(childBox, flags); this._arrows[i].allocate(childBox, flags);
} }
} },
// We override SwitcherList's _onItemEnter method to delay // We override SwitcherList's _onItemEnter method to delay
// activation when the thumbnail list is open // activation when the thumbnail list is open
@@ -795,17 +827,16 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
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, mask] = 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);
} },
// We override SwitcherList's highlight() method to also deal with // We override SwitcherList's highlight() method to also deal with
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window // the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
@@ -822,7 +853,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._arrows[this._curApp].remove_style_pseudo_class('highlighted'); this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
} }
super.highlight(n, justOutline); this.parent(n, justOutline);
this._curApp = n; this._curApp = n;
if (this._curApp != -1) { if (this._curApp != -1) {
@@ -831,7 +862,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
else else
this._arrows[this._curApp].add_style_pseudo_class('highlighted'); this._arrows[this._curApp].add_style_pseudo_class('highlighted');
} }
} },
_addIcon(appIcon) { _addIcon(appIcon) {
this.icons.push(appIcon); this.icons.push(appIcon);
@@ -842,8 +873,9 @@ 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);
@@ -851,7 +883,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
arrow.hide(); arrow.hide();
else else
item.add_accessible_state (Atk.StateType.EXPANDABLE); item.add_accessible_state (Atk.StateType.EXPANDABLE);
} },
_removeIcon(app) { _removeIcon(app) {
let index = this.icons.findIndex(icon => { let index = this.icons.findIndex(icon => {
@@ -862,13 +894,15 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this.icons.splice(index, 1); this.icons.splice(index, 1);
this.removeItem(index); this.removeItem(index);
} },
}); });
var ThumbnailList = GObject.registerClass( var ThumbnailList = new Lang.Class({
class ThumbnailList extends SwitcherPopup.SwitcherList { Name: 'ThumbnailList',
Extends: SwitcherPopup.SwitcherList,
_init(windows) { _init(windows) {
super._init(false); this.parent(false);
this._labels = new Array(); this._labels = new Array();
this._thumbnailBins = new Array(); this._thumbnailBins = new Array();
@@ -901,7 +935,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
} }
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} },
addClones(availHeight) { addClones(availHeight) {
if (!this._thumbnailBins.length) if (!this._thumbnailBins.length)
@@ -934,7 +968,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
// Make sure we only do this once // Make sure we only do this once
this._thumbnailBins = new Array(); this._thumbnailBins = new Array();
} },
_removeThumbnail(source, clone) { _removeThumbnail(source, clone) {
let index = this._clones.indexOf(clone); let index = this._clones.indexOf(clone);
@@ -950,20 +984,23 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
this.highlight(SwitcherPopup.mod(index, this._clones.length)); this.highlight(SwitcherPopup.mod(index, this._clones.length));
else else
this.destroy(); this.destroy();
} },
_onDestroy() { _onDestroy() {
this._clones.forEach(clone => { this._clones.forEach(clone => {
if (clone.source) if (clone.source)
clone.source.disconnect(clone._destroyId); clone.source.disconnect(clone._destroyId);
}); });
} },
}); });
var WindowIcon = GObject.registerClass( var WindowIcon = new Lang.Class({
class WindowIcon extends St.BoxLayout { Name: 'WindowIcon',
Extends: St.BoxLayout,
_init(window, mode) { _init(window, mode) {
super._init({ style_class: 'alt-tab-app', this.parent({ style_class: 'alt-tab-app',
vertical: true }); vertical: true });
this.window = window; this.window = window;
@@ -1004,7 +1041,7 @@ class WindowIcon extends St.BoxLayout {
} }
this._icon.set_size(size * scaleFactor, size * scaleFactor); this._icon.set_size(size * scaleFactor, size * scaleFactor);
} },
_createAppIcon(app, size) { _createAppIcon(app, size) {
let appIcon = app ? app.create_icon_texture(size) let appIcon = app ? app.create_icon_texture(size)
@@ -1017,10 +1054,12 @@ class WindowIcon extends St.BoxLayout {
} }
}); });
var WindowList = GObject.registerClass( var WindowList = new Lang.Class({
class WindowList extends SwitcherPopup.SwitcherList { Name: 'WindowList',
Extends: SwitcherPopup.SwitcherList,
_init(windows, mode) { _init(windows, mode) {
super._init(true); this.parent(true);
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER, this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
@@ -1037,21 +1076,21 @@ class WindowList extends SwitcherPopup.SwitcherList {
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)
}); });
} }
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} },
_onDestroy() { _onDestroy() {
this.icons.forEach(icon => { this.icons.forEach(icon => {
icon.window.disconnect(icon._unmanagedSignalId); icon.window.disconnect(icon._unmanagedSignalId);
}); });
} },
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(forWidth) {
let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth); let [minHeight, natHeight] = this.parent(forWidth);
let spacing = this.get_theme_node().get_padding(St.Side.BOTTOM); let spacing = this.get_theme_node().get_padding(St.Side.BOTTOM);
let [labelMin, labelNat] = this._label.get_preferred_height(-1); let [labelMin, labelNat] = this._label.get_preferred_height(-1);
@@ -1060,7 +1099,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
natHeight += labelNat + spacing; natHeight += labelNat + spacing;
return [minHeight, natHeight]; return [minHeight, natHeight];
} },
vfunc_allocate(box, flags) { vfunc_allocate(box, flags) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@@ -1073,24 +1112,24 @@ 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;
childBox.y2 = box.y2 - totalLabelHeight; childBox.y2 = box.y2 - totalLabelHeight;
super.vfunc_allocate(childBox, flags); this.parent(childBox, flags);
// Hooking up the parent vfunc will call this.set_allocation() with // Hooking up the parent vfunc will call this.set_allocation() with
// the height without the label height, so call it again with the // the height without the label height, so call it again with the
// correct size here. // correct size here.
this.set_allocation(box, flags); this.set_allocation(box, flags);
} },
highlight(index, justOutline) { highlight(index, justOutline) {
super.highlight(index, justOutline); this.parent(index, justOutline);
this._label.set_text(index == -1 ? '' : this.icons[index].label.text); this._label.set_text(index == -1 ? '' : this.icons[index].label.text);
} },
_removeWindow(window) { _removeWindow(window) {
let index = this.icons.findIndex(icon => { let index = this.icons.findIndex(icon => {

View File

@@ -1,27 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { GLib, Gio, St } = imports.gi; const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const St = imports.gi.St;
const Tweener = imports.ui.tweener; const Signals = imports.signals;
const Atk = imports.gi.Atk;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16; var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 0.3;
var SPINNER_ANIMATION_DELAY = 1.0;
var Animation = class { var Animation = new Lang.Class({
constructor(file, width, height, speed) { Name: 'Animation',
_init(file, width, height, speed) {
this.actor = new St.Bin(); this.actor = new St.Bin();
this.actor.set_size(width, height);
this.actor.connect('destroy', this._onDestroy.bind(this)); this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
this.actor.connect('resource-scale-changed',
this._loadFile.bind(this, file, width, height));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
this._scaleChangedId = themeContext.connect('notify::scale-factor',
this._loadFile.bind(this, file, width, height));
this._speed = speed; this._speed = speed;
this._isLoaded = false; this._isLoaded = false;
@@ -29,8 +22,11 @@ var Animation = class {
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() {
if (this._isLoaded && this._timeoutId == 0) { if (this._isLoaded && this._timeoutId == 0) {
@@ -42,7 +38,7 @@ var Animation = class {
} }
this._isPlaying = true; this._isPlaying = true;
} },
stop() { stop() {
if (this._timeoutId > 0) { if (this._timeoutId > 0) {
@@ -51,24 +47,7 @@ var Animation = class {
} }
this._isPlaying = false; this._isPlaying = false;
} },
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
this._isLoaded = false;
this.actor.destroy_all_children();
if (!validResourceScale)
return;
let 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.actor.set_child(this._animations);
}
_showFrame(frame) { _showFrame(frame) {
let oldFrameActor = this._animations.get_child_at_index(this._frame); let oldFrameActor = this._animations.get_child_at_index(this._frame);
@@ -80,94 +59,30 @@ var Animation = class {
let newFrameActor = this._animations.get_child_at_index(this._frame); let newFrameActor = this._animations.get_child_at_index(this._frame);
if (newFrameActor) if (newFrameActor)
newFrameActor.show(); newFrameActor.show();
} },
_update() { _update() {
this._showFrame(this._frame + 1); this._showFrame(this._frame + 1);
return GLib.SOURCE_CONTINUE; return GLib.SOURCE_CONTINUE;
} },
_syncAnimationSize() {
if (!this._isLoaded)
return;
let [width, height] = this.actor.get_size();
for (let i = 0; i < this._animations.get_n_children(); ++i)
this._animations.get_child_at_index(i).set_size(width, height);
}
_animationsLoaded() { _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 = class extends Animation { var AnimatedIcon = new Lang.Class({
constructor(file, size) { Name: 'AnimatedIcon',
super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); Extends: Animation,
}
};
var Spinner = class extends AnimatedIcon { _init(file, size) {
constructor(size, animate = false) { this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super(file, size);
this.actor.opacity = 0;
this._animate = animate;
} }
});
_onDestroy() {
this._animate = false;
super._onDestroy();
}
play() {
Tweener.removeTweens(this.actor);
if (this._animate) {
super.play();
Tweener.addTween(this.actor, {
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
time: SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
this.actor.opacity = 255;
super.play();
}
}
stop() {
Tweener.removeTweens(this.actor);
if (this._animate) {
Tweener.addTween(this.actor, {
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => {
super.stop();
}
});
} else {
this.actor.opacity = 0;
super.stop();
}
}
};

File diff suppressed because it is too large Load Diff

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 Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -14,63 +15,53 @@ 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-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',
'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',
'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',
}; };
class AppFavorites { var AppFavorites = new Lang.Class({
constructor() { Name: 'AppFavorites',
this.FAVORITE_APPS_KEY = 'favorite-apps';
FAVORITE_APPS_KEY: 'favorite-apps',
_init() {
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();
} },
_onFavsChanged() { _onFavsChanged() {
this.reload(); this.reload();
this.emit('changed'); this.emit('changed');
} },
reload() { reload() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY); let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
@@ -98,29 +89,29 @@ class AppFavorites {
let app = apps[i]; let app = apps[i];
this._favorites[app.get_id()] = app; this._favorites[app.get_id()] = app;
} }
} },
_getIds() { _getIds() {
let ret = []; let ret = [];
for (let id in this._favorites) for (let id in this._favorites)
ret.push(id); ret.push(id);
return ret; return ret;
} },
getFavoriteMap() { getFavoriteMap() {
return this._favorites; return this._favorites;
} },
getFavorites() { getFavorites() {
let ret = []; let ret = [];
for (let id in this._favorites) for (let id in this._favorites)
ret.push(this._favorites[id]); ret.push(this._favorites[id]);
return ret; return ret;
} },
isFavorite(appId) { isFavorite(appId) {
return appId in this._favorites; return appId in this._favorites;
} },
_addFavorite(appId, pos) { _addFavorite(appId, pos) {
if (appId in this._favorites) if (appId in this._favorites)
@@ -138,7 +129,7 @@ class AppFavorites {
ids.splice(pos, 0, appId); ids.splice(pos, 0, appId);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids); global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
return true; return true;
} },
addFavoriteAtPos(appId, pos) { addFavoriteAtPos(appId, pos) {
if (!this._addFavorite(appId, pos)) if (!this._addFavorite(appId, pos))
@@ -152,25 +143,25 @@ class AppFavorites {
this._removeFavorite(appId); this._removeFavorite(appId);
} }
}); });
} },
addFavorite(appId) { addFavorite(appId) {
this.addFavoriteAtPos(appId, -1); this.addFavoriteAtPos(appId, -1);
} },
moveFavoriteToPos(appId, pos) { moveFavoriteToPos(appId, pos) {
this._removeFavorite(appId); this._removeFavorite(appId);
this._addFavorite(appId, pos); this._addFavorite(appId, pos);
} },
_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);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids); global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
return true; return true;
} },
removeFavorite(appId) { removeFavorite(appId) {
let ids = this._getIds(); let ids = this._getIds();
@@ -187,7 +178,7 @@ class AppFavorites {
} }
}); });
} }
} });
Signals.addSignalMethods(AppFavorites.prototype); Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null; var appFavoritesInstance = null;

View File

@@ -1,4 +1,10 @@
const { 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 Lang = imports.lang;
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;
@@ -13,11 +19,12 @@ var AudioDevice = {
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection'); const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
var AudioDeviceSelectionDialog = GObject.registerClass({ var AudioDeviceSelectionDialog = new Lang.Class({
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } } Name: 'AudioDeviceSelectionDialog',
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog { Extends: ModalDialog.ModalDialog,
_init(devices) { _init(devices) {
super._init({ styleClass: 'audio-device-selection-dialog' }); this.parent({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {}; this._deviceItems = {};
@@ -32,7 +39,11 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
if (this._selectionBox.get_n_children() < 2) if (this._selectionBox.get_n_children() < 2)
throw new Error('Too few devices for a selection'); throw new Error('Too few devices for a selection');
} },
destroy() {
this.parent();
},
_buildLayout(devices) { _buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title', let title = new St.Label({ style_class: 'audio-selection-title',
@@ -45,16 +56,15 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' }); this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
this.contentLayout.add(this._selectionBox, { expand: true }); this.contentLayout.add(this._selectionBox, { expand: true });
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.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:
@@ -64,10 +74,10 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
default: default:
return null; return null;
} }
} },
_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:
@@ -77,7 +87,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
default: default:
return null; return null;
} }
} },
_addDevice(device) { _addDevice(device) {
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box', let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
@@ -107,14 +117,14 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
this.close(); this.close();
Main.overview.hide(); Main.overview.hide();
}); });
} },
_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;
} }
@@ -124,19 +134,21 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
} }
}); });
var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus { var AudioDeviceSelectionDBus = new Lang.Class({
constructor() { Name: 'AudioDeviceSelectionDBus',
_init() {
this._audioSelectionDialog = null; this._audioSelectionDialog = null;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell/AudioDeviceSelection');
Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null); Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null);
} },
_onDialogClosed() { _onDialogClosed() {
this._audioSelectionDialog = null; this._audioSelectionDialog = null;
} },
_onDeviceSelected(dialog, device) { _onDeviceSelected(dialog, device) {
let connection = this._dbusImpl.get_connection(); let connection = this._dbusImpl.get_connection();
@@ -149,7 +161,7 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
info ? info.name : null, info ? info.name : null,
'DeviceSelected', 'DeviceSelected',
GLib.Variant.new('(s)', [deviceName])); GLib.Variant.new('(s)', [deviceName]));
} },
OpenAsync(params, invocation) { OpenAsync(params, invocation) {
if (this._audioSelectionDialog) { if (this._audioSelectionDialog) {
@@ -159,12 +171,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;
} }
@@ -177,7 +189,7 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
this._audioSelectionDialog = dialog; this._audioSelectionDialog = dialog;
invocation.return_value(null); invocation.return_value(null);
} },
CloseAsync(params, invocation) { CloseAsync(params, invocation) {
if (this._audioSelectionDialog && if (this._audioSelectionDialog &&
@@ -186,4 +198,4 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
invocation.return_value(null); invocation.return_value(null);
} }
}; });

View File

@@ -93,7 +93,13 @@
// MetaBackgroundImage MetaBackgroundImage // MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage // MetaBackgroundImage MetaBackgroundImage
const { Clutter, GDesktopEnums, Gio, GLib, 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 Lang = imports.lang;
const Meta = imports.gi.Meta;
const Signals = imports.signals; const Signals = imports.signals;
const LoginManager = imports.misc.loginManager; const LoginManager = imports.misc.loginManager;
@@ -108,6 +114,7 @@ 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 = 1.0; var FADE_ANIMATION_TIME = 1.0;
@@ -131,12 +138,14 @@ function _fileEqual0(file1, file2) {
return file1.equal(file2); return file1.equal(file2);
} }
var BackgroundCache = class BackgroundCache { var BackgroundCache = new Lang.Class({
constructor() { Name: 'BackgroundCache',
_init() {
this._fileMonitors = {}; this._fileMonitors = {};
this._backgroundSources = {}; this._backgroundSources = {};
this._animations = {}; this._animations = {};
} },
monitorFile(file) { monitorFile(file) {
let key = file.hash(); let key = file.hash();
@@ -154,7 +163,7 @@ var BackgroundCache = class BackgroundCache {
}); });
this._fileMonitors[key] = monitor; this._fileMonitors[key] = monitor;
} },
getAnimation(params) { getAnimation(params) {
params = Params.parse(params, { file: null, params = Params.parse(params, { file: null,
@@ -186,7 +195,7 @@ var BackgroundCache = class BackgroundCache {
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded'); GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
} }
}); });
} },
getBackgroundSource(layoutManager, settingsSchema) { getBackgroundSource(layoutManager, settingsSchema) {
// The layoutManager is always the same one; we pass in it since // The layoutManager is always the same one; we pass in it since
@@ -200,7 +209,7 @@ var BackgroundCache = class BackgroundCache {
} }
return this._backgroundSources[settingsSchema]; return this._backgroundSources[settingsSchema];
} },
releaseBackgroundSource(settingsSchema) { releaseBackgroundSource(settingsSchema) {
if (settingsSchema in this._backgroundSources) { if (settingsSchema in this._backgroundSources) {
@@ -212,7 +221,7 @@ var BackgroundCache = class BackgroundCache {
} }
} }
} }
}; });
Signals.addSignalMethods(BackgroundCache.prototype); Signals.addSignalMethods(BackgroundCache.prototype);
function getBackgroundCache() { function getBackgroundCache() {
@@ -221,8 +230,10 @@ function getBackgroundCache() {
return _backgroundCache; return _backgroundCache;
} }
var Background = class Background { var Background = new Lang.Class({
constructor(params) { Name: '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,
@@ -256,15 +267,14 @@ var Background = class Background {
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();
} },
destroy() { destroy() {
this.background = null;
this._cancellable.cancel(); this._cancellable.cancel();
this._removeAnimationTimeout(); this._removeAnimationTimeout();
@@ -288,28 +298,12 @@ var Background = class Background {
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('changed');
return GLib.SOURCE_REMOVE;
});
}
updateResolution() { updateResolution() {
if (this._animation) if (this._animation)
this._refreshAnimation(); this._refreshAnimation();
} },
_refreshAnimation() { _refreshAnimation() {
if (!this._animation) if (!this._animation)
@@ -317,7 +311,7 @@ var Background = class Background {
this._removeAnimationTimeout(); this._removeAnimationTimeout();
this._updateAnimation(); this._updateAnimation();
} },
_setLoaded() { _setLoaded() {
if (this.isLoaded) if (this.isLoaded)
@@ -330,7 +324,7 @@ var Background = class Background {
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit'); GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
} },
_loadPattern() { _loadPattern() {
let colorString, res, color, secondColor; let colorString, res, color, secondColor;
@@ -346,7 +340,7 @@ var Background = class Background {
this.background.set_color(color); this.background.set_color(color);
else else
this.background.set_gradient(shadingType, color, secondColor); this.background.set_gradient(shadingType, color, secondColor);
} },
_watchFile(file) { _watchFile(file) {
let key = file.hash(); let key = file.hash();
@@ -359,18 +353,18 @@ var Background = class Background {
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;
} },
_removeAnimationTimeout() { _removeAnimationTimeout() {
if (this._updateAnimationTimeoutId) { if (this._updateAnimationTimeoutId) {
GLib.source_remove(this._updateAnimationTimeoutId); GLib.source_remove(this._updateAnimationTimeoutId);
this._updateAnimationTimeoutId = 0; this._updateAnimationTimeoutId = 0;
} }
} },
_updateAnimation() { _updateAnimation() {
this._updateAnimationTimeoutId = 0; this._updateAnimationTimeoutId = 0;
@@ -410,7 +404,7 @@ var Background = class Background {
}); });
} }
} }
} },
_queueUpdateAnimation() { _queueUpdateAnimation() {
if (this._updateAnimationTimeoutId != 0) if (this._updateAnimationTimeoutId != 0)
@@ -439,7 +433,7 @@ var Background = class Background {
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation'); GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
} },
_loadAnimation(file) { _loadAnimation(file) {
this._cache.getAnimation({ file: file, this._cache.getAnimation({ file: file,
@@ -456,7 +450,7 @@ var Background = class Background {
this._watchFile(file); this._watchFile(file);
} }
}); });
} },
_loadImage(file) { _loadImage(file) {
this.background.set_file(file, this._style); this.background.set_file(file, this._style);
@@ -464,22 +458,22 @@ var Background = class Background {
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);
}); });
} }
} },
_loadFile(file) { _loadFile(file) {
if (file.get_basename().endsWith('.xml')) if (file.get_basename().endsWith('.xml'))
this._loadAnimation(file); this._loadAnimation(file);
else else
this._loadImage(file); this._loadImage(file);
} },
_load() { _load() {
this._cache = getBackgroundCache(); this._cache = getBackgroundCache();
@@ -492,14 +486,16 @@ var Background = class Background {
} }
this._loadFile(this._file); this._loadFile(this._file);
} },
}; });
Signals.addSignalMethods(Background.prototype); Signals.addSignalMethods(Background.prototype);
let _systemBackground; let _systemBackground;
var SystemBackground = class SystemBackground { var SystemBackground = new Lang.Class({
constructor() { Name: 'SystemBackground',
_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) {
@@ -528,12 +524,14 @@ var SystemBackground = class SystemBackground {
image = null; image = null;
}); });
} }
} },
}; });
Signals.addSignalMethods(SystemBackground.prototype); Signals.addSignalMethods(SystemBackground.prototype);
var BackgroundSource = class BackgroundSource { var BackgroundSource = new Lang.Class({
constructor(layoutManager, settingsSchema) { Name: 'BackgroundSource',
_init(layoutManager, settingsSchema) {
// Allow override the background image setting for performance testing // Allow override the background image setting for performance testing
this._layoutManager = layoutManager; this._layoutManager = layoutManager;
this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE'); this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE');
@@ -544,7 +542,7 @@ var BackgroundSource = class BackgroundSource {
this._monitorsChangedId = this._monitorsChangedId =
monitorManager.connect('monitors-changed', monitorManager.connect('monitors-changed',
this._onMonitorsChanged.bind(this)); this._onMonitorsChanged.bind(this));
} },
_onMonitorsChanged() { _onMonitorsChanged() {
for (let monitorIndex in this._backgrounds) { for (let monitorIndex in this._backgrounds) {
@@ -558,7 +556,7 @@ var BackgroundSource = class BackgroundSource {
delete this._backgrounds[monitorIndex]; delete this._backgrounds[monitorIndex];
} }
} }
} },
getBackground(monitorIndex) { getBackground(monitorIndex) {
let file = null; let file = null;
@@ -605,7 +603,7 @@ var BackgroundSource = class BackgroundSource {
} }
return this._backgrounds[monitorIndex]; return this._backgrounds[monitorIndex];
} },
destroy() { destroy() {
let monitorManager = Meta.MonitorManager.get(); let monitorManager = Meta.MonitorManager.get();
@@ -619,10 +617,12 @@ var BackgroundSource = class BackgroundSource {
this._backgrounds = null; this._backgrounds = null;
} }
}; });
var Animation = class Animation { var Animation = new Lang.Class({
constructor(params) { Name: 'Animation',
_init(params) {
params = Params.parse(params, { file: null }); params = Params.parse(params, { file: null });
this.file = params.file; this.file = params.file;
@@ -630,7 +630,7 @@ var Animation = class Animation {
this.transitionProgress = 0.0; this.transitionProgress = 0.0;
this.transitionDuration = 0.0; this.transitionDuration = 0.0;
this.loaded = false; this.loaded = false;
} },
load(callback) { load(callback) {
this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() }); this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
@@ -640,7 +640,7 @@ var Animation = class Animation {
if (callback) if (callback)
callback(); callback();
}); });
} },
update(monitor) { update(monitor) {
this.keyFrameFiles = []; this.keyFrameFiles = [];
@@ -661,12 +661,14 @@ var Animation = class Animation {
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); Signals.addSignalMethods(Animation.prototype);
var BackgroundManager = class BackgroundManager { var BackgroundManager = new Lang.Class({
constructor(params) { Name: 'BackgroundManager',
_init(params) {
params = Params.parse(params, { container: null, params = Params.parse(params, { container: null,
layoutManager: Main.layoutManager, layoutManager: Main.layoutManager,
monitorIndex: null, monitorIndex: null,
@@ -686,7 +688,7 @@ var BackgroundManager = class BackgroundManager {
this.backgroundActor = this._createBackgroundActor(); this.backgroundActor = this._createBackgroundActor();
this._newBackgroundActor = null; this._newBackgroundActor = null;
} },
destroy() { destroy() {
let cache = getBackgroundCache(); let cache = getBackgroundCache();
@@ -702,7 +704,7 @@ var BackgroundManager = class BackgroundManager {
this.backgroundActor.destroy(); this.backgroundActor.destroy();
this.backgroundActor = null; this.backgroundActor = null;
} }
} },
_swapBackgroundActor() { _swapBackgroundActor() {
let oldBackgroundActor = this.backgroundActor; let oldBackgroundActor = this.backgroundActor;
@@ -715,10 +717,11 @@ var BackgroundManager = class BackgroundManager {
time: FADE_ANIMATION_TIME, time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete() { onComplete() {
oldBackgroundActor.background.run_dispose();
oldBackgroundActor.destroy(); oldBackgroundActor.destroy();
} }
}); });
} },
_updateBackgroundActor() { _updateBackgroundActor() {
if (this._newBackgroundActor) { if (this._newBackgroundActor) {
@@ -747,7 +750,7 @@ var BackgroundManager = class BackgroundManager {
this._swapBackgroundActor(); this._swapBackgroundActor();
}); });
} }
} },
_createBackgroundActor() { _createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex); let background = this._backgroundSource.getBackground(this._monitorIndex);
@@ -761,8 +764,10 @@ 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);
backgroundActor.lower_bottom(); backgroundActor.lower_bottom();
} }
@@ -782,6 +787,6 @@ var BackgroundManager = class BackgroundManager {
}); });
return backgroundActor; return backgroundActor;
} },
}; });
Signals.addSignalMethods(BackgroundManager.prototype); Signals.addSignalMethods(BackgroundManager.prototype);

View File

@@ -1,14 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
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;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu { var BackgroundMenu = new Lang.Class({
constructor(layoutManager) { Name: 'BackgroundMenu',
super(layoutManager.dummyCursor, 0, St.Side.TOP); Extends: PopupMenu.PopupMenu,
_init(layoutManager) {
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop'); this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@@ -20,12 +26,12 @@ var BackgroundMenu = class BackgroundMenu extends PopupMenu.PopupMenu {
layoutManager.uiGroup.add_actor(this.actor); layoutManager.uiGroup.add_actor(this.actor);
this.actor.hide(); this.actor.hide();
} }
}; });
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) {

View File

@@ -1,10 +1,16 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const { Atk, Clutter, St } = imports.gi; const Atk = imports.gi.Atk;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
var BarLevel = class { var BarLevel = new Lang.Class({
constructor(value, params) { Name: "BarLevel",
_init(value, params) {
if (isNaN(value)) if (isNaN(value))
// Avoid spreading NaNs around // Avoid spreading NaNs around
throw TypeError('The bar level value must be a number'); throw TypeError('The bar level value must be a number');
@@ -14,7 +20,7 @@ var BarLevel = class {
this._barLevelWidth = 0; this._barLevelWidth = 0;
if (params == undefined) if (params == undefined)
params = {}; params = {}
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel', this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
can_focus: params['canFocus'] || false, can_focus: params['canFocus'] || false,
@@ -34,7 +40,7 @@ var BarLevel = class {
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this)); this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('value-changed', this._valueChanged.bind(this)); this.connect('value-changed', this._valueChanged.bind(this));
} },
setValue(value) { setValue(value) {
if (isNaN(value)) if (isNaN(value))
@@ -42,7 +48,7 @@ var BarLevel = class {
this._value = Math.max(Math.min(value, this._maxValue), 0); this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint(); this.actor.queue_repaint();
} },
setMaximumValue(value) { setMaximumValue(value) {
if (isNaN(value)) if (isNaN(value))
@@ -51,7 +57,7 @@ var BarLevel = class {
this._maxValue = Math.max(value, 1); this._maxValue = Math.max(value, 1);
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue); this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.actor.queue_repaint(); this.actor.queue_repaint();
} },
setOverdriveStart(value) { setOverdriveStart(value) {
if (isNaN(value)) if (isNaN(value))
@@ -63,7 +69,7 @@ var BarLevel = class {
this._overdriveStart = value; this._overdriveStart = value;
this._value = Math.max(Math.min(value, this._maxValue), 0); this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint(); this.actor.queue_repaint();
} },
_barLevelRepaint(area) { _barLevelRepaint(area) {
let cr = area.get_context(); let cr = area.get_context();
@@ -105,7 +111,7 @@ var BarLevel = class {
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);
@@ -117,11 +123,10 @@ var BarLevel = class {
/* 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);
@@ -144,19 +149,17 @@ var BarLevel = class {
} }
/* 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) {
@@ -173,34 +176,35 @@ var BarLevel = class {
} }
cr.$dispose(); cr.$dispose();
} },
_getCurrentValue(actor) { _getCurrentValue(actor) {
return this._value; return this._value;
} },
_getOverdriveStart(actor) { _getOverdriveStart(actor) {
return this._overdriveStart; return this._overdriveStart;
} },
_getMinimumValue(actor) { _getMinimumValue(actor) {
return 0; return 0;
} },
_getMaximumValue(actor) { _getMaximumValue(actor) {
return this._maxValue; return this._maxValue;
} },
_setCurrentValue(actor, value) { _setCurrentValue(actor, value) {
this._value = value; this._value = value;
} },
_valueChanged(barLevel, value, property) { _valueChanged(barLevel, value, property) {
this._customAccessible.notify("accessible-value"); this._customAccessible.notify("accessible-value");
} },
get value() { get value() {
return this._value; return this._value;
} }
}; });
Signals.addSignalMethods(BarLevel.prototype); Signals.addSignalMethods(BarLevel.prototype);

View File

@@ -1,6 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GObject, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
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; const Tweener = imports.ui.tweener;
@@ -24,14 +29,18 @@ var POPUP_ANIMATION_TIME = 0.15;
* 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 = new Lang.Class({
Name: 'BoxPointer',
Extends: St.Widget,
Signals: { 'arrow-side-changed': {} }, Signals: { 'arrow-side-changed': {} },
}, class BoxPointer extends St.Widget {
_init(arrowSide, binProperties) { _init(arrowSide, binProperties) {
super._init(); this.parent();
this.actor = this;
this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
@@ -45,36 +54,61 @@ var BoxPointer = GObject.registerClass({
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.bin.raise(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._capturedEventId = 0; this._capturedEventId = 0;
this._muteInput(); this._muteInput();
},
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId);
delete this._sourceActorDestroyId;
}
}
get arrowSide() { get arrowSide() {
return this._arrowSide; return this._arrowSide;
} },
_muteInput() { _muteInput() {
if (this._capturedEventId == 0) if (this._capturedEventId == 0)
this._capturedEventId = this.connect('captured-event', this._capturedEventId = this.connect('captured-event',
() => Clutter.EVENT_STOP); () => Clutter.EVENT_STOP);
} },
_unmuteInput() { _unmuteInput() {
if (this._capturedEventId != 0) { if (this._capturedEventId != 0) {
this.disconnect(this._capturedEventId); this.disconnect(this._capturedEventId);
this._capturedEventId = 0; 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();
@@ -91,23 +125,23 @@ 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;
} }
} }
Tweener.addTween(this, { opacity: 255, Tweener.addTween(this, { opacity: 255,
translation_x: 0, xOffset: 0,
translation_y: 0, yOffset: 0,
transition: 'linear', transition: 'linear',
onComplete: () => { onComplete: () => {
this._unmuteInput(); this._unmuteInput();
@@ -115,14 +149,14 @@ var BoxPointer = GObject.registerClass({
onComplete(); onComplete();
}, },
time: animationTime }); 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);
@@ -131,16 +165,16 @@ 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:
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;
} }
} }
@@ -149,20 +183,20 @@ var BoxPointer = GObject.registerClass({
Tweener.removeTweens(this); Tweener.removeTweens(this);
Tweener.addTween(this, { opacity: fade ? 0 : 255, Tweener.addTween(this, { opacity: fade ? 0 : 255,
translation_x: translationX, xOffset: xOffset,
translation_y: translationY, yOffset: yOffset,
transition: 'linear', transition: 'linear',
time: animationTime, time: animationTime,
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();
} }
}); });
} },
_adjustAllocationForArrow(isWidth, minSize, natSize) { _adjustAllocationForArrow(isWidth, minSize, natSize) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@@ -177,7 +211,7 @@ var BoxPointer = GObject.registerClass({
} }
return [minSize, natSize]; return [minSize, natSize];
} },
vfunc_get_preferred_width(forHeight) { vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@@ -187,7 +221,7 @@ var BoxPointer = GObject.registerClass({
width = this._adjustAllocationForArrow(true, ...width); width = this._adjustAllocationForArrow(true, ...width);
return themeNode.adjust_preferred_width(...width); return themeNode.adjust_preferred_width(...width);
} },
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@@ -198,16 +232,19 @@ var BoxPointer = GObject.registerClass({
height = this._adjustAllocationForArrow(false, ...height); height = this._adjustAllocationForArrow(false, ...height);
return themeNode.adjust_preferred_height(...height); return themeNode.adjust_preferred_height(...height);
} },
vfunc_allocate(box, flags) { vfunc_allocate(box, flags) {
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;
@@ -236,11 +273,10 @@ 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);
}
} }
},
_drawBorder(area) { _drawBorder(area) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
@@ -264,7 +300,7 @@ 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');
@@ -345,7 +381,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) {
@@ -366,7 +402,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) {
@@ -387,7 +423,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) {
@@ -396,7 +432,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);
@@ -408,7 +444,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);
@@ -422,29 +458,19 @@ var BoxPointer = GObject.registerClass({
} }
cr.$dispose(); cr.$dispose();
} },
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) {
this._sourceAlignment = alignment; this._sourceAlignment = alignment;
@@ -453,20 +479,16 @@ var BoxPointer = GObject.registerClass({
return; return;
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 [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
@@ -474,7 +496,7 @@ var BoxPointer = GObject.registerClass({
// 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');
@@ -513,7 +535,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];
@@ -524,8 +546,8 @@ 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))) {
@@ -543,8 +565,8 @@ 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))) {
@@ -568,9 +590,10 @@ 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
// the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from // the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
@@ -580,7 +603,7 @@ var BoxPointer = GObject.registerClass({
this._arrowOrigin = origin; this._arrowOrigin = origin;
this._border.queue_repaint(); this._border.queue_repaint();
} }
} },
// @actor: an actor relative to which the arrow is positioned. // @actor: an actor relative to which the arrow is positioned.
// Differently from setPosition, this will not move the boxpointer itself, // Differently from setPosition, this will not move the boxpointer itself,
@@ -590,59 +613,95 @@ var BoxPointer = GObject.registerClass({
this._arrowActor = actor; this._arrowActor = actor;
this._border.queue_repaint(); this._border.queue_repaint();
} }
} },
_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 [minWidth, minHeight, 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;
} }
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();
this.emit('arrow-side-changed'); this.emit('arrow-side-changed');
} },
getPadding(side) { getPadding(side) {
return this.bin.get_theme_node().get_padding(side); return this.bin.get_theme_node().get_padding(side);
} },
getArrowHeight() { getArrowHeight() {
return this.get_theme_node().get_length('-arrow-rise'); return this.get_theme_node().get_length('-arrow-rise');

View File

@@ -1,7 +1,13 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageList = imports.ui.messageList; const MessageList = imports.ui.messageList;
@@ -9,15 +15,13 @@ const MessageTray = imports.ui.messageTray;
const Mpris = imports.ui.mpris; const Mpris = imports.ui.mpris;
const Util = imports.misc.util; const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
var MSECS_IN_DAY = 24 * 60 * 60 * 1000; var MSECS_IN_DAY = 24 * 60 * 60 * 1000;
var SHOW_WEEKDATE_KEY = 'show-weekdate'; var SHOW_WEEKDATE_KEY = 'show-weekdate';
var ELLIPSIS_CHAR = '\u2026'; var ELLIPSIS_CHAR = '\u2026';
var MESSAGE_ICON_SIZE = -1; // pick up from CSS var MESSAGE_ICON_SIZE = -1; // pick up from CSS
var NC_ = (context, str) => `${context}\u0004${str}`; var NC_ = (context, str) => context + '\u0004' + str;
function sameYear(dateA, dateB) { function sameYear(dateA, dateB) {
return (dateA.getYear() == dateB.getYear()); return (dateA.getYear() == dateB.getYear());
@@ -38,7 +42,7 @@ function isToday(date) {
function _isWorkDay(date) { function _isWorkDay(date) {
/* Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). */ /* Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). */
let days = C_('calendar-no-work', "06"); let days = C_('calendar-no-work', "06");
return !days.includes(date.getDay().toString()); return days.indexOf(date.getDay().toString()) == -1;
} }
function _getBeginningOfDay(date) { function _getBeginningOfDay(date) {
@@ -85,45 +89,64 @@ function _getCalendarDayAbbreviation(dayNumber) {
// Abstraction for an appointment/event in a calendar // Abstraction for an appointment/event in a calendar
var CalendarEvent = class CalendarEvent { var CalendarEvent = new Lang.Class({
constructor(id, date, end, summary, allDay) { Name: 'CalendarEvent',
_init(id, date, end, summary, allDay) {
this.id = id; this.id = id;
this.date = date; this.date = date;
this.end = end; this.end = end;
this.summary = summary; this.summary = summary;
this.allDay = allDay; this.allDay = allDay;
} }
}; });
// Interface for appointments/events - e.g. the contents of a calendar // Interface for appointments/events - e.g. the contents of a calendar
// //
// First, an implementation with no events // First, an implementation with no events
var EmptyEventSource = class EmptyEventSource { var EmptyEventSource = new Lang.Class({
constructor() { Name: 'EmptyEventSource',
_init() {
this.isLoading = false; this.isLoading = false;
this.isDummy = true; this.isDummy = true;
this.hasCalendars = false; this.hasCalendars = false;
} },
destroy() { destroy() {
} },
ignoreEvent(event) {
},
requestRange(begin, end) { requestRange(begin, end) {
} },
getEvents(begin, end) { getEvents(begin, end) {
let result = []; let result = [];
return result; return result;
} },
hasEvents(day) { hasEvents(day) {
return false; return false;
} }
}; });
Signals.addSignalMethods(EmptyEventSource.prototype); Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = loadInterfaceXML('org.gnome.Shell.CalendarServer'); const CalendarServerIface = `
<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>`;
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface); const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
@@ -143,7 +166,8 @@ function _datesEqual(a, b) {
return true; return true;
} }
function _dateIntervalsOverlap(a0, a1, b0, b1) { function _dateIntervalsOverlap(a0, a1, b0, b1)
{
if (a1 <= b0) if (a1 <= b0)
return false; return false;
else if (b1 <= a0) else if (b1 <= a0)
@@ -153,12 +177,22 @@ function _dateIntervalsOverlap(a0, a1, b0, b1) {
} }
// an implementation that reads data from a session bus service // an implementation that reads data from a session bus service
var DBusEventSource = class DBusEventSource { var DBusEventSource = new Lang.Class({
constructor() { Name: 'DBusEventSource',
_init() {
this._resetCache(); this._resetCache();
this.isLoading = false; this.isLoading = false;
this.isDummy = false; this.isDummy = false;
this._ignoredEvents = new Map();
let savedState = global.get_persistent_state('as', 'ignored_events');
if (savedState)
savedState.deep_unpack().forEach(eventId => {
this._ignoredEvents.set(eventId, true);
});
this._initialized = false; this._initialized = false;
this._dbusProxy = new CalendarServer(); this._dbusProxy = new CalendarServer();
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => { this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
@@ -167,7 +201,7 @@ var DBusEventSource = class DBusEventSource {
try { try {
this._dbusProxy.init_finish(result); this._dbusProxy.init_finish(result);
loaded = true; loaded = true;
} catch (e) { } catch(e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) { if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
// Ignore timeouts and install signals as normal, because with high // Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a // probability the service will appear later on, and we will get a
@@ -177,7 +211,7 @@ var DBusEventSource = class DBusEventSource {
// about the HasCalendars property and would cause an exception trying // about the HasCalendars property and would cause an exception trying
// to read it) // to read it)
} else { } else {
log(`Error loading calendars: ${e.message}`); log('Error loading calendars: ' + e.message);
return; return;
} }
} }
@@ -201,39 +235,39 @@ var DBusEventSource = class DBusEventSource {
this._onNameAppeared(); this._onNameAppeared();
} }
}); });
} },
destroy() { destroy() {
this._dbusProxy.run_dispose(); this._dbusProxy.run_dispose();
} },
get hasCalendars() { get hasCalendars() {
if (this._initialized) if (this._initialized)
return this._dbusProxy.HasCalendars; return this._dbusProxy.HasCalendars;
else else
return false; return false;
} },
_resetCache() { _resetCache() {
this._events = []; this._events = [];
this._lastRequestBegin = null; this._lastRequestBegin = null;
this._lastRequestEnd = null; this._lastRequestEnd = null;
} },
_onNameAppeared(owner) { _onNameAppeared(owner) {
this._initialized = true; this._initialized = true;
this._resetCache(); this._resetCache();
this._loadEvents(true); this._loadEvents(true);
} },
_onNameVanished(oldOwner) { _onNameVanished(oldOwner) {
this._resetCache(); this._resetCache();
this.emit('changed'); this.emit('changed');
} },
_onChanged() { _onChanged() {
this._loadEvents(false); this._loadEvents(false);
} },
_onEventsReceived(results, error) { _onEventsReceived(results, error) {
let newEvents = []; let newEvents = [];
@@ -255,21 +289,31 @@ var DBusEventSource = class DBusEventSource {
this._events = newEvents; this._events = newEvents;
this.isLoading = false; this.isLoading = false;
this.emit('changed'); this.emit('changed');
} },
_loadEvents(forceReload) { _loadEvents(forceReload) {
// Ignore while loading // Ignore while loading
if (!this._initialized) if (!this._initialized)
return; return;
if (this._curRequestBegin && this._curRequestEnd) { if (this._curRequestBegin && this._curRequestEnd){
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000, this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000, this._curRequestEnd.getTime() / 1000,
forceReload, forceReload,
this._onEventsReceived.bind(this), this._onEventsReceived.bind(this),
Gio.DBusCallFlags.NONE); Gio.DBusCallFlags.NONE);
} }
} },
ignoreEvent(event) {
if (this._ignoredEvents.get(event.id))
return;
this._ignoredEvents.set(event.id, true);
let savedState = new GLib.Variant('as', [...this._ignoredEvents.keys()]);
global.set_persistent_state('ignored_events', savedState);
this.emit('changed');
},
requestRange(begin, end) { requestRange(begin, end) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) { if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
@@ -280,13 +324,16 @@ var DBusEventSource = class DBusEventSource {
this._curRequestEnd = end; this._curRequestEnd = end;
this._loadEvents(false); this._loadEvents(false);
} }
} },
getEvents(begin, end) { getEvents(begin, end) {
let result = []; let result = [];
for (let n = 0; n < this._events.length; n++) { for(let n = 0; n < this._events.length; n++) {
let event = this._events[n]; let event = this._events[n];
if (this._ignoredEvents.has(event.id))
continue;
if (_dateIntervalsOverlap (event.date, event.end, begin, end)) { if (_dateIntervalsOverlap (event.date, event.end, begin, end)) {
result.push(event); result.push(event);
} }
@@ -298,7 +345,7 @@ var DBusEventSource = class DBusEventSource {
return d1.getTime() - d2.getTime(); return d1.getTime() - d2.getTime();
}); });
return result; return result;
} },
hasEvents(day) { hasEvents(day) {
let dayBegin = _getBeginningOfDay(day); let dayBegin = _getBeginningOfDay(day);
@@ -311,15 +358,17 @@ var DBusEventSource = class DBusEventSource {
return true; return true;
} }
}; });
Signals.addSignalMethods(DBusEventSource.prototype); Signals.addSignalMethods(DBusEventSource.prototype);
var Calendar = class Calendar { var Calendar = new Lang.Class({
constructor() { Name: 'Calendar',
_init() {
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' }); this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
this._settings.connect(`changed::${SHOW_WEEKDATE_KEY}`, this._onSettingsChange.bind(this)); this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, this._onSettingsChange.bind(this));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
/** /**
@@ -353,7 +402,7 @@ var Calendar = class Calendar {
this._onScroll.bind(this)); this._onScroll.bind(this));
this._buildHeader (); this._buildHeader ();
} },
// @eventSource: is an object implementing the EventSource API, e.g. the // @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal. // requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
@@ -365,7 +414,7 @@ var Calendar = class Calendar {
}); });
this._rebuildCalendar(); this._rebuildCalendar();
this._update(); this._update();
} },
// Sets the calendar to show a specific date // Sets the calendar to show a specific date
setDate(date) { setDate(date) {
@@ -375,14 +424,14 @@ var Calendar = class Calendar {
this._selectedDate = date; this._selectedDate = date;
this._update(); this._update();
this.emit('selected-date-changed', new Date(this._selectedDate)); this.emit('selected-date-changed', new Date(this._selectedDate));
} },
updateTimeZone() { updateTimeZone() {
// The calendar need to be rebuilt after a time zone update because // The calendar need to be rebuilt after a time zone update because
// the date might have changed. // the date might have changed.
this._rebuildCalendar(); this._rebuildCalendar();
this._update(); this._update();
} },
_buildHeader() { _buildHeader() {
let layout = this.actor.layout_manager; let layout = this.actor.layout_manager;
@@ -401,7 +450,7 @@ var Calendar = class Calendar {
this._topBox.add(this._backButton); this._topBox.add(this._backButton);
this._backButton.connect('clicked', this._onPrevMonthButtonClicked.bind(this)); this._backButton.connect('clicked', this._onPrevMonthButtonClicked.bind(this));
this._monthLabel = new St.Label({ style_class: 'calendar-month-label', this._monthLabel = new St.Label({style_class: 'calendar-month-label',
can_focus: true }); can_focus: true });
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE }); this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
@@ -439,7 +488,7 @@ var Calendar = class Calendar {
// All the children after this are days, and get removed when we update the calendar // All the children after this are days, and get removed when we update the calendar
this._firstDayIndex = this.actor.get_n_children(); this._firstDayIndex = this.actor.get_n_children();
} },
_onScroll(actor, event) { _onScroll(actor, event) {
switch (event.get_scroll_direction()) { switch (event.get_scroll_direction()) {
@@ -453,7 +502,7 @@ var Calendar = class Calendar {
break; break;
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} },
_onPrevMonthButtonClicked() { _onPrevMonthButtonClicked() {
let newDate = new Date(this._selectedDate); let newDate = new Date(this._selectedDate);
@@ -465,7 +514,8 @@ var Calendar = class Calendar {
let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate(); let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate();
newDate = new Date(newDate.getFullYear() - 1, 11, day); newDate = new Date(newDate.getFullYear() - 1, 11, day);
} }
} else { }
else {
newDate.setMonth(oldMonth - 1); newDate.setMonth(oldMonth - 1);
if (newDate.getMonth() != oldMonth - 1) { if (newDate.getMonth() != oldMonth - 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate(); let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate();
@@ -476,7 +526,7 @@ var Calendar = class Calendar {
this._backButton.grab_key_focus(); this._backButton.grab_key_focus();
this.setDate(newDate); this.setDate(newDate);
} },
_onNextMonthButtonClicked() { _onNextMonthButtonClicked() {
let newDate = new Date(this._selectedDate); let newDate = new Date(this._selectedDate);
@@ -488,7 +538,8 @@ var Calendar = class Calendar {
let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate(); let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate();
newDate = new Date(newDate.getFullYear() + 1, 0, day); newDate = new Date(newDate.getFullYear() + 1, 0, day);
} }
} else { }
else {
newDate.setMonth(oldMonth + 1); newDate.setMonth(oldMonth + 1);
if (newDate.getMonth() != oldMonth + 1) { if (newDate.getMonth() != oldMonth + 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate(); let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate();
@@ -499,14 +550,14 @@ var Calendar = class Calendar {
this._forwardButton.grab_key_focus(); this._forwardButton.grab_key_focus();
this.setDate(newDate); this.setDate(newDate);
} },
_onSettingsChange() { _onSettingsChange() {
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY); this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
this._buildHeader(); this._buildHeader();
this._rebuildCalendar(); this._rebuildCalendar();
this._update(); this._update();
} },
_rebuildCalendar() { _rebuildCalendar() {
let now = new Date(); let now = new Date();
@@ -543,6 +594,8 @@ var Calendar = class Calendar {
this._calendarBegin = new Date(beginDate); this._calendarBegin = new Date(beginDate);
this._markedAsToday = now; this._markedAsToday = now;
let year = beginDate.getYear();
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7; let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
let startsOnWeekStart = daysToWeekStart == 0; let startsOnWeekStart = daysToWeekStart == 0;
let weekPadding = startsOnWeekStart ? 7 : 0; let weekPadding = startsOnWeekStart ? 7 : 0;
@@ -554,7 +607,7 @@ var Calendar = class Calendar {
let row = 2; let row = 2;
// nRows here means 6 weeks + one header + one navbar // nRows here means 6 weeks + one header + one navbar
let nRows = 8; let nRows = 8;
while (row < nRows) { while (row < 8) {
// xgettext:no-javascript-format // xgettext:no-javascript-format
let button = new St.Button({ label: iter.toLocaleFormat(C_("date day number format", "%d")), let button = new St.Button({ label: iter.toLocaleFormat(C_("date day number format", "%d")),
can_focus: true }); can_focus: true });
@@ -580,12 +633,12 @@ var Calendar = class Calendar {
// Hack used in lieu of border-collapse - see gnome-shell.css // Hack used in lieu of border-collapse - see gnome-shell.css
if (row == 2) if (row == 2)
styleClass = `calendar-day-top ${styleClass}`; styleClass = 'calendar-day-top ' + styleClass;
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7 let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart; : iter.getDay() == this._weekStart;
if (leftMost) if (leftMost)
styleClass = `calendar-day-left ${styleClass}`; styleClass = 'calendar-day-left ' + styleClass;
if (sameDay(now, iter)) if (sameDay(now, iter))
styleClass += ' calendar-today'; styleClass += ' calendar-today';
@@ -625,7 +678,7 @@ var Calendar = class Calendar {
// Signal to the event source that we are interested in events // Signal to the event source that we are interested in events
// only from this date range // only from this date range
this._eventSource.requestRange(beginDate, iter); this._eventSource.requestRange(beginDate, iter);
} },
_update() { _update() {
let now = new Date(); let now = new Date();
@@ -643,22 +696,23 @@ var Calendar = class Calendar {
button.add_style_pseudo_class('selected'); button.add_style_pseudo_class('selected');
if (this._shouldDateGrabFocus) if (this._shouldDateGrabFocus)
button.grab_key_focus(); button.grab_key_focus();
} else {
button.remove_style_pseudo_class('selected');
} }
else
button.remove_style_pseudo_class('selected');
}); });
} }
}; });
Signals.addSignalMethods(Calendar.prototype); Signals.addSignalMethods(Calendar.prototype);
var EventMessage = class EventMessage extends MessageList.Message { var EventMessage = new Lang.Class({
constructor(event, date) { Name: 'EventMessage',
super('', event.summary); Extends: MessageList.Message,
_init(event, date) {
this._event = event; this._event = event;
this._date = date; this._date = date;
this.setTitle(this._formatEventTime()); this.parent(this._formatEventTime(), event.summary);
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' }); this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon); this.setIcon(this._icon);
@@ -667,7 +721,7 @@ var EventMessage = class EventMessage extends MessageList.Message {
let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child'); let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = (iconVisible ? 255 : 0); this._icon.opacity = (iconVisible ? 255 : 0);
}); });
} },
_formatEventTime() { _formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date); let periodBegin = _getBeginningOfDay(this._date);
@@ -700,17 +754,23 @@ var EventMessage = class EventMessage extends MessageList.Message {
title = title + ELLIPSIS_CHAR; title = title + ELLIPSIS_CHAR;
} }
return title; return title;
},
canClose() {
return isToday(this._date);
} }
}; });
var NotificationMessage = var NotificationMessage = new Lang.Class({
class NotificationMessage extends MessageList.Message { Name: 'NotificationMessage',
constructor(notification) { Extends: MessageList.Message,
super(notification.title, notification.bannerBodyText);
this.setUseBodyMarkup(notification.bannerBodyMarkup);
_init(notification) {
this.notification = notification; this.notification = notification;
this.parent(notification.title, notification.bannerBodyText);
this.setUseBodyMarkup(notification.bannerBodyMarkup);
this.setIcon(this._getIcon()); this.setIcon(this._getIcon());
this.connect('close', () => { this.connect('close', () => {
@@ -719,14 +779,13 @@ class NotificationMessage extends MessageList.Message {
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED); this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
}); });
this._destroyId = notification.connect('destroy', () => { this._destroyId = notification.connect('destroy', () => {
this._disconnectNotificationSignals();
this.notification = null; this.notification = null;
if (!this._closed) if (!this._closed)
this.close(); this.close();
}); });
this._updatedId = notification.connect('updated', this._updatedId = notification.connect('updated',
this._onUpdated.bind(this)); this._onUpdated.bind(this));
} },
_getIcon() { _getIcon() {
if (this.notification.gicon) if (this.notification.gicon)
@@ -734,25 +793,22 @@ class NotificationMessage extends MessageList.Message {
icon_size: MESSAGE_ICON_SIZE }); icon_size: MESSAGE_ICON_SIZE });
else else
return this.notification.source.createIcon(MESSAGE_ICON_SIZE); return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
} },
_onUpdated(n, clear) { _onUpdated(n, clear) {
this.setIcon(this._getIcon()); this.setIcon(this._getIcon());
this.setTitle(n.title); this.setTitle(n.title);
this.setBody(n.bannerBodyText); this.setBody(n.bannerBodyText);
this.setUseBodyMarkup(n.bannerBodyMarkup); this.setUseBodyMarkup(n.bannerBodyMarkup);
} },
_onClicked() { _onClicked() {
this.notification.activate(); this.notification.activate();
} },
_onDestroy() { _onDestroy() {
super._onDestroy(); this.parent();
this._disconnectNotificationSignals();
}
_disconnectNotificationSignals() {
if (this._updatedId) if (this._updatedId)
this.notification.disconnect(this._updatedId); this.notification.disconnect(this._updatedId);
this._updatedId = 0; this._updatedId = 0;
@@ -761,22 +817,21 @@ class NotificationMessage extends MessageList.Message {
this.notification.disconnect(this._destroyId); this.notification.disconnect(this._destroyId);
this._destroyId = 0; this._destroyId = 0;
} }
});
canClose() { var EventsSection = new Lang.Class({
return true; Name: 'EventsSection',
} Extends: MessageList.MessageListSection,
};
var EventsSection = class EventsSection extends MessageList.MessageListSection {
constructor() {
super();
_init() {
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', this._reloadEvents.bind(this)); this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
this._eventSource = new EmptyEventSource(); this._eventSource = new EmptyEventSource();
this._messageById = new Map(); this._messageById = new Map();
this.parent();
this._title = new St.Button({ style_class: 'events-section-title', this._title = new St.Button({ style_class: 'events-section-title',
label: '', label: '',
x_align: St.Align.START, x_align: St.Align.START,
@@ -789,16 +844,20 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
Shell.AppSystem.get_default().connect('installed-changed', Shell.AppSystem.get_default().connect('installed-changed',
this._appInstalledChanged.bind(this)); this._appInstalledChanged.bind(this));
this._appInstalledChanged(); this._appInstalledChanged();
} },
_ignoreEvent(event) {
this._eventSource.ignoreEvent(event);
},
setEventSource(eventSource) { setEventSource(eventSource) {
this._eventSource = eventSource; this._eventSource = eventSource;
this._eventSource.connect('changed', this._reloadEvents.bind(this)); this._eventSource.connect('changed', this._reloadEvents.bind(this));
} },
get allowed() { get allowed() {
return Main.sessionMode.showCalendarEvents; return Main.sessionMode.showCalendarEvents;
} },
_updateTitle() { _updateTitle() {
this._title.visible = !isToday(this._date); this._title.visible = !isToday(this._date);
@@ -817,7 +876,7 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
dayFormat = Shell.util_translate_time_string(NC_("calendar heading", dayFormat = Shell.util_translate_time_string(NC_("calendar heading",
"%A, %B %-d, %Y")); "%A, %B %-d, %Y"));
this._title.label = this._date.toLocaleFormat(dayFormat); this._title.label = this._date.toLocaleFormat(dayFormat);
} },
_reloadEvents() { _reloadEvents() {
if (this._eventSource.isLoading) if (this._eventSource.isLoading)
@@ -843,6 +902,9 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
let message = this._messageById.get(event.id); let message = this._messageById.get(event.id);
if (!message) { if (!message) {
message = new EventMessage(event, this._date); message = new EventMessage(event, this._date);
message.connect('close', () => {
this._ignoreEvent(event);
});
this._messageById.set(event.id, message); this._messageById.set(event.id, message);
this.addMessage(message, false); this.addMessage(message, false);
} else { } else {
@@ -852,12 +914,12 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
this._reloading = false; this._reloading = false;
this._sync(); this._sync();
} },
_appInstalledChanged() { _appInstalledChanged() {
this._calendarApp = undefined; this._calendarApp = undefined;
this._title.reactive = (this._getCalendarApp() != null); this._title.reactive = (this._getCalendarApp() != null);
} },
_getCalendarApp() { _getCalendarApp() {
if (this._calendarApp !== undefined) if (this._calendarApp !== undefined)
@@ -872,7 +934,7 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
this._calendarApp = null; this._calendarApp = null;
} }
return this._calendarApp; return this._calendarApp;
} },
_onTitleClicked() { _onTitleClicked() {
Main.overview.hide(); Main.overview.hide();
@@ -882,30 +944,32 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
if (app.get_id() == 'evolution.desktop') if (app.get_id() == 'evolution.desktop')
app = Gio.DesktopAppInfo.new('evolution-calendar.desktop'); app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
app.launch([], global.create_app_launch_context(0, -1)); app.launch([], global.create_app_launch_context(0, -1));
} },
setDate(date) { setDate(date) {
super.setDate(date); this.parent(date);
this._updateTitle(); this._updateTitle();
this._reloadEvents(); this._reloadEvents();
} },
_shouldShow() { _shouldShow() {
return !this.empty || !isToday(this._date); return !this.empty || !isToday(this._date);
} },
_sync() { _sync() {
if (this._reloading) if (this._reloading)
return; return;
super._sync(); this.parent();
} }
}; });
var NotificationSection = var NotificationSection = new Lang.Class({
class NotificationSection extends MessageList.MessageListSection { Name: 'NotificationSection',
constructor() { Extends: MessageList.MessageListSection,
super();
_init() {
this.parent();
this._sources = new Map(); this._sources = new Map();
this._nUrgent = 0; this._nUrgent = 0;
@@ -916,12 +980,12 @@ class NotificationSection extends MessageList.MessageListSection {
}); });
this.actor.connect('notify::mapped', this._onMapped.bind(this)); this.actor.connect('notify::mapped', this._onMapped.bind(this));
} },
get allowed() { get allowed() {
return Main.sessionMode.hasNotifications && return Main.sessionMode.hasNotifications &&
!Main.sessionMode.isGreeter; !Main.sessionMode.isGreeter;
} },
_createTimeLabel(datetime) { _createTimeLabel(datetime) {
let label = new St.Label({ style_class: 'event-time', let label = new St.Label({ style_class: 'event-time',
@@ -932,7 +996,7 @@ class NotificationSection extends MessageList.MessageListSection {
label.text = Util.formatTimeSpan(datetime); label.text = Util.formatTimeSpan(datetime);
}); });
return label; return label;
} },
_sourceAdded(tray, source) { _sourceAdded(tray, source) {
let obj = { let obj = {
@@ -947,7 +1011,7 @@ class NotificationSection extends MessageList.MessageListSection {
this._onNotificationAdded.bind(this)); this._onNotificationAdded.bind(this));
this._sources.set(source, obj); this._sources.set(source, obj);
} },
_onNotificationAdded(source, notification) { _onNotificationAdded(source, notification) {
let message = new NotificationMessage(notification); let message = new NotificationMessage(notification);
@@ -978,14 +1042,14 @@ class NotificationSection extends MessageList.MessageListSection {
let index = isUrgent ? 0 : this._nUrgent; let index = isUrgent ? 0 : this._nUrgent;
this.addMessageAtIndex(message, index, this.actor.mapped); this.addMessageAtIndex(message, index, this.actor.mapped);
} },
_onSourceDestroy(source, obj) { _onSourceDestroy(source, obj) {
source.disconnect(obj.destroyId); source.disconnect(obj.destroyId);
source.disconnect(obj.notificationAddedId); source.disconnect(obj.notificationAddedId);
this._sources.delete(source); this._sources.delete(source);
} },
_onMapped() { _onMapped() {
if (!this.actor.mapped) if (!this.actor.mapped)
@@ -994,15 +1058,17 @@ class NotificationSection extends MessageList.MessageListSection {
for (let message of this._messages.keys()) for (let message of this._messages.keys())
if (message.notification.urgency != MessageTray.Urgency.CRITICAL) if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
message.notification.acknowledged = true; message.notification.acknowledged = true;
} },
_shouldShow() { _shouldShow() {
return !this.empty && isToday(this._date); return !this.empty && isToday(this._date);
} }
}; });
var Placeholder = class Placeholder { var Placeholder = new Lang.Class({
constructor() { Name: 'Placeholder',
_init() {
this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder', this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
vertical: true }); vertical: true });
@@ -1020,14 +1086,14 @@ var Placeholder = class Placeholder {
this.actor.add_actor(this._label); this.actor.add_actor(this._label);
this._sync(); this._sync();
} },
setDate(date) { setDate(date) {
if (sameDay(this._date, date)) if (sameDay(this._date, date))
return; return;
this._date = date; this._date = date;
this._sync(); this._sync();
} },
_sync() { _sync() {
let today = isToday(this._date); let today = isToday(this._date);
@@ -1044,10 +1110,12 @@ var Placeholder = class Placeholder {
this._label.text = _("No Events"); this._label.text = _("No Events");
} }
} }
}; });
var CalendarMessageList = class CalendarMessageList { var CalendarMessageList = new Lang.Class({
constructor() { Name: 'CalendarMessageList',
_init() {
this.actor = new St.Widget({ style_class: 'message-list', this.actor = new St.Widget({ style_class: 'message-list',
layout_manager: new Clutter.BinLayout(), layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true }); x_expand: true, y_expand: true });
@@ -1063,16 +1131,16 @@ var CalendarMessageList = class CalendarMessageList {
overlay_scrollbars: true, overlay_scrollbars: true,
x_expand: true, y_expand: true, x_expand: true, y_expand: true,
x_fill: true, y_fill: true }); x_fill: true, y_fill: true });
this._scrollView.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC); this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
box.add_actor(this._scrollView); box.add_actor(this._scrollView);
this._clearButton = new St.Button({ style_class: 'message-list-clear-button button', this._clearButton = new St.Button({ style_class: 'message-list-clear-button button',
label: _("Clear"), label: _("Clear All"),
can_focus: true }); can_focus: true });
this._clearButton.set_x_align(Clutter.ActorAlign.END); this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => { this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()]; let sections = [...this._sections.keys()];
sections.forEach((s) => s.clear()); sections.forEach((s) => { s.clear(); });
}); });
box.add_actor(this._clearButton); box.add_actor(this._clearButton);
@@ -1093,7 +1161,7 @@ var CalendarMessageList = class CalendarMessageList {
this._addSection(this._eventsSection); this._addSection(this._eventsSection);
Main.sessionMode.connect('updated', this._sync.bind(this)); Main.sessionMode.connect('updated', this._sync.bind(this));
} },
_addSection(section) { _addSection(section) {
let obj = { let obj = {
@@ -1118,7 +1186,7 @@ var CalendarMessageList = class CalendarMessageList {
this._sections.set(section, obj); this._sections.set(section, obj);
this._sectionList.add_actor(section.actor); this._sectionList.add_actor(section.actor);
this._sync(); this._sync();
} },
_removeSection(section) { _removeSection(section) {
let obj = this._sections.get(section); let obj = this._sections.get(section);
@@ -1131,11 +1199,11 @@ var CalendarMessageList = class CalendarMessageList {
this._sections.delete(section); this._sections.delete(section);
this._sectionList.remove_actor(section.actor); this._sectionList.remove_actor(section.actor);
this._sync(); this._sync();
} },
_onKeyFocusIn(section, actor) { _onKeyFocusIn(section, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor); Util.ensureActorVisibleInScrollView(this._scrollView, actor);
} },
_sync() { _sync() {
let sections = [...this._sections.keys()]; let sections = [...this._sections.keys()];
@@ -1150,15 +1218,15 @@ var CalendarMessageList = class CalendarMessageList {
let canClear = sections.some(s => s.canClear && s.actor.visible); let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear; this._clearButton.reactive = canClear;
} },
setEventSource(eventSource) { setEventSource(eventSource) {
this._eventsSection.setEventSource(eventSource); this._eventsSection.setEventSource(eventSource);
} },
setDate(date) { setDate(date) {
for (let section of this._sections.keys()) for (let section of this._sections.keys())
section.setDate(date); section.setDate(date);
this._placeholder.setDate(date); this._placeholder.setDate(date);
} }
}; });

View File

@@ -1,7 +1,13 @@
const { Clutter, Pango, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
var CheckBox = class CheckBox { const Lang = imports.lang;
constructor(label) {
var CheckBox = new Lang.Class({
Name: 'CheckBox',
_init(label) {
let container = new St.BoxLayout(); let container = new St.BoxLayout();
this.actor = new St.Button({ style_class: 'check-box', this.actor = new St.Button({ style_class: 'check-box',
child: container, child: container,
@@ -22,13 +28,13 @@ var CheckBox = class CheckBox {
if (label) if (label)
this.setLabel(label); this.setLabel(label);
} },
setLabel(label) { setLabel(label) {
this._label.set_text(label); this._label.set_text(label);
} },
getLabelActor() { getLabelActor() {
return this._label; return this._label;
} }
}; });

View File

@@ -1,38 +1,46 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
var FROZEN_WINDOW_BRIGHTNESS = -0.3; var FROZEN_WINDOW_BRIGHTNESS = -0.3
var DIALOG_TRANSITION_TIME = 0.15; var DIALOG_TRANSITION_TIME = 0.15
var ALIVE_TIMEOUT = 5000; var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({ var CloseDialog = new Lang.Class({
Implements: [Meta.CloseDialog], Name: 'CloseDialog',
Extends: GObject.Object,
Implements: [ Meta.CloseDialog ],
Properties: { Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog) 'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
}, },
}, class CloseDialog extends GObject.Object {
_init(window) { _init(window) {
super._init(); this.parent();
this._window = window; this._window = window;
this._dialog = null; this._dialog = null;
this._tracked = undefined; this._tracked = undefined;
this._timeoutId = 0; this._timeoutId = 0;
this._windowFocusChangedId = 0; this._windowFocusChangedId = 0;
this._keyFocusChangedId = 0; this._keyFocusChangedId = 0;
} },
get window() { get window() {
return this._window; return this._window;
} },
set window(window) { set window(window) {
this._window = window; this._window = window;
} },
_createDialogContent() { _createDialogContent() {
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
@@ -44,7 +52,7 @@ var CloseDialog = GObject.registerClass({
"continue or force the application to quit entirely."); "continue or force the application to quit entirely.");
let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' }); let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
return new Dialog.MessageDialogContent({ icon, title, subtitle }); return new Dialog.MessageDialogContent({ icon, title, subtitle });
} },
_initDialog() { _initDialog() {
if (this._dialog) if (this._dialog)
@@ -64,7 +72,7 @@ var CloseDialog = GObject.registerClass({
key: Clutter.Escape }); key: Clutter.Escape });
global.focus_manager.add_group(this._dialog); global.focus_manager.add_group(this._dialog);
} },
_addWindowEffect() { _addWindowEffect() {
// We set the effect on the surface actor, so the dialog itself // We set the effect on the surface actor, so the dialog itself
@@ -75,21 +83,21 @@ var CloseDialog = GObject.registerClass({
let effect = new Clutter.BrightnessContrastEffect(); let effect = new Clutter.BrightnessContrastEffect();
effect.set_brightness(FROZEN_WINDOW_BRIGHTNESS); effect.set_brightness(FROZEN_WINDOW_BRIGHTNESS);
surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect); surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect);
} },
_removeWindowEffect() { _removeWindowEffect() {
let windowActor = this._window.get_compositor_private(); let windowActor = this._window.get_compositor_private();
let surfaceActor = windowActor.get_first_child(); let surfaceActor = windowActor.get_first_child();
surfaceActor.remove_effect_by_name("gnome-shell-frozen-window"); surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
} },
_onWait() { _onWait() {
this.response(Meta.CloseDialogResponse.WAIT); this.response(Meta.CloseDialogResponse.WAIT);
} },
_onClose() { _onClose() {
this.response(Meta.CloseDialogResponse.FORCE_CLOSE); this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
} },
_onFocusChanged() { _onFocusChanged() {
if (Meta.is_wayland_compositor()) if (Meta.is_wayland_compositor())
@@ -120,7 +128,7 @@ var CloseDialog = GObject.registerClass({
}); });
this._tracked = shouldTrack; this._tracked = shouldTrack;
} },
vfunc_show() { vfunc_show() {
if (this._dialog != null) if (this._dialog != null)
@@ -154,7 +162,7 @@ var CloseDialog = GObject.registerClass({
time: DIALOG_TRANSITION_TIME, time: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this) onComplete: this._onFocusChanged.bind(this)
}); });
} },
vfunc_hide() { vfunc_hide() {
if (this._dialog == null) if (this._dialog == null)
@@ -165,7 +173,7 @@ var CloseDialog = GObject.registerClass({
GLib.source_remove(this._timeoutId); GLib.source_remove(this._timeoutId);
this._timeoutId = 0; this._timeoutId = 0;
global.display.disconnect(this._windowFocusChangedId); global.display.disconnect(this._windowFocusChangedId)
this._windowFocusChangedId = 0; this._windowFocusChangedId = 0;
global.stage.disconnect(this._keyFocusChangedId); global.stage.disconnect(this._keyFocusChangedId);
@@ -183,7 +191,7 @@ var CloseDialog = GObject.registerClass({
dialog.destroy(); dialog.destroy();
} }
}); });
} },
vfunc_focus() { vfunc_focus() {
if (this._dialog) if (this._dialog)

View File

@@ -1,36 +1,40 @@
const Lang = imports.lang;
const Main = imports.ui.main; const Main = imports.ui.main;
var ComponentManager = class { var ComponentManager = new Lang.Class({
constructor() { Name: 'ComponentManager',
_init() {
this._allComponents = {}; this._allComponents = {};
this._enabledComponents = []; this._enabledComponents = [];
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated(); this._sessionUpdated();
} },
_sessionUpdated() { _sessionUpdated() {
let newEnabledComponents = Main.sessionMode.components; let newEnabledComponents = Main.sessionMode.components;
newEnabledComponents.filter( newEnabledComponents.filter(
name => !this._enabledComponents.includes(name) name => this._enabledComponents.indexOf(name) == -1
).forEach(name => { ).forEach(name => {
this._enableComponent(name); this._enableComponent(name);
}); });
this._enabledComponents.filter( this._enabledComponents.filter(
name => !newEnabledComponents.includes(name) name => newEnabledComponents.indexOf(name) == -1
).forEach(name => { ).forEach(name => {
this._disableComponent(name); this._disableComponent(name);
}); });
this._enabledComponents = newEnabledComponents; this._enabledComponents = newEnabledComponents;
} },
_importComponent(name) { _importComponent(name) {
let module = imports.ui.components[name]; let module = imports.ui.components[name];
return module.Component; return module.Component;
} },
_ensureComponent(name) { _ensureComponent(name) {
let component = this._allComponents[name]; let component = this._allComponents[name];
@@ -44,13 +48,13 @@ var ComponentManager = class {
component = new constructor(); component = new constructor();
this._allComponents[name] = component; this._allComponents[name] = component;
return component; return component;
} },
_enableComponent(name) { _enableComponent(name) {
let component = this._ensureComponent(name); let component = this._ensureComponent(name);
if (component) if (component)
component.enable(); component.enable();
} },
_disableComponent(name) { _disableComponent(name) {
let component = this._allComponents[name]; let component = this._allComponents[name];
@@ -58,4 +62,4 @@ var ComponentManager = class {
return; return;
component.disable(); component.disable();
} }
}; });

View File

@@ -1,8 +1,11 @@
// -*- 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 Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Params = imports.misc.params; const Params = imports.misc.params;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -16,8 +19,10 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
var AUTORUN_EXPIRE_TIMEOUT_SECS = 10; var AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
var AutomountManager = class { var AutomountManager = new Lang.Class({
constructor() { Name: 'AutomountManager',
_init() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._volumeQueue = []; this._volumeQueue = [];
this._activeOperations = new Map(); this._activeOperations = new Map();
@@ -29,7 +34,7 @@ var AutomountManager = class {
this._inhibited = false; this._inhibited = false;
this._volumeMonitor = Gio.VolumeMonitor.get(); this._volumeMonitor = Gio.VolumeMonitor.get();
} },
enable() { enable() {
this._volumeAddedId = this._volumeMonitor.connect('volume-added', this._onVolumeAdded.bind(this)); this._volumeAddedId = this._volumeMonitor.connect('volume-added', this._onVolumeAdded.bind(this));
@@ -40,7 +45,7 @@ var AutomountManager = class {
this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this)); this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll'); GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
} },
disable() { disable() {
this._volumeMonitor.disconnect(this._volumeAddedId); this._volumeMonitor.disconnect(this._volumeAddedId);
@@ -53,7 +58,7 @@ var AutomountManager = class {
Mainloop.source_remove(this._mountAllId); Mainloop.source_remove(this._mountAllId);
this._mountAllId = 0; this._mountAllId = 0;
} }
} },
_InhibitorsChanged(object, senderName, [inhibtor]) { _InhibitorsChanged(object, senderName, [inhibtor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT, this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
@@ -62,7 +67,7 @@ var AutomountManager = class {
this._inhibited = result[0]; this._inhibited = result[0];
} }
}); });
} },
_startupMountAll() { _startupMountAll() {
let volumes = this._volumeMonitor.get_volumes(); let volumes = this._volumeMonitor.get_volumes();
@@ -74,7 +79,7 @@ var AutomountManager = class {
this._mountAllId = 0; this._mountAllId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} },
_onDriveConnected() { _onDriveConnected() {
// if we're not in the current ConsoleKit session, // if we're not in the current ConsoleKit session,
@@ -82,11 +87,10 @@ var AutomountManager = class {
if (!this._session.SessionIsActive) if (!this._session.SessionIsActive)
return; return;
let player = global.display.get_sound_player(); global.play_theme_sound(0, 'device-added-media',
player.play_from_theme('device-added-media',
_("External drive connected"), _("External drive connected"),
null); null);
} },
_onDriveDisconnected() { _onDriveDisconnected() {
// if we're not in the current ConsoleKit session, // if we're not in the current ConsoleKit session,
@@ -94,11 +98,10 @@ var AutomountManager = class {
if (!this._session.SessionIsActive) if (!this._session.SessionIsActive)
return; return;
let player = global.display.get_sound_player(); global.play_theme_sound(0, 'device-removed-media',
player.play_from_theme('device-removed-media',
_("External drive disconnected"), _("External drive disconnected"),
null); null);
} },
_onDriveEjectButton(monitor, drive) { _onDriveEjectButton(monitor, drive) {
// TODO: this code path is not tested, as the GVfs volume monitor // TODO: this code path is not tested, as the GVfs volume monitor
@@ -109,29 +112,31 @@ var AutomountManager = class {
// we force stop/eject in this case, so we don't have to pass a // we force stop/eject in this case, so we don't have to pass a
// mount operation object // mount operation object
if (drive.can_stop()) { if (drive.can_stop()) {
drive.stop(Gio.MountUnmountFlags.FORCE, null, null, drive.stop
(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => { (drive, res) => {
try { try {
drive.stop_finish(res); drive.stop_finish(res);
} catch (e) { } catch (e) {
log(`Unable to stop the drive after drive-eject-button ${e.toString()}`); log("Unable to stop the drive after drive-eject-button " + e.toString());
} }
}); });
} else if (drive.can_eject()) { } else if (drive.can_eject()) {
drive.eject_with_operation(Gio.MountUnmountFlags.FORCE, null, null, drive.eject_with_operation
(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => { (drive, res) => {
try { try {
drive.eject_with_operation_finish(res); drive.eject_with_operation_finish(res);
} catch (e) { } catch (e) {
log(`Unable to eject the drive after drive-eject-button ${e.toString()}`); log("Unable to eject the drive after drive-eject-button " + e.toString());
} }
}); });
} }
} },
_onVolumeAdded(monitor, volume) { _onVolumeAdded(monitor, volume) {
this._checkAndMountVolume(volume); this._checkAndMountVolume(volume);
} },
_checkAndMountVolume(volume, params) { _checkAndMountVolume(volume, params) {
params = Params.parse(params, { checkSession: true, params = Params.parse(params, { checkSession: true,
@@ -171,7 +176,7 @@ var AutomountManager = class {
} else { } else {
this._mountVolume(volume, null, params.allowAutorun); this._mountVolume(volume, null, params.allowAutorun);
} }
} },
_mountVolume(volume, operation, allowAutorun) { _mountVolume(volume, operation, allowAutorun) {
if (allowAutorun) if (allowAutorun)
@@ -182,7 +187,7 @@ var AutomountManager = class {
volume.mount(0, mountOp, null, volume.mount(0, mountOp, null,
this._onVolumeMounted.bind(this)); this._onVolumeMounted.bind(this));
} },
_onVolumeMounted(volume, res) { _onVolumeMounted(volume, res) {
this._allowAutorunExpire(volume); this._allowAutorunExpire(volume);
@@ -198,24 +203,16 @@ var AutomountManager = class {
// error strings are not unique for the cases in the comments below. // error strings are not unique for the cases in the comments below.
if (e.message.includes('No key available with this passphrase') || // cryptsetup if (e.message.includes('No key available with this passphrase') || // cryptsetup
e.message.includes('No key available to unlock device') || // udisks (no password) e.message.includes('No key available to unlock device') || // udisks (no password)
// libblockdev wrong password opening LUKS device e.message.includes('Error unlocking')) { // udisks (wrong password)
e.message.includes('Failed to activate device: Incorrect passphrase') ||
// cryptsetup returns EINVAL in many cases, including wrong TCRYPT password/parameters
e.message.includes('Failed to load device\'s parameters: Invalid argument')) {
this._reaskPassword(volume); this._reaskPassword(volume);
} else { } else {
if (e.message.includes('Compiled against a version of libcryptsetup that does not support the VeraCrypt PIM setting')) {
Main.notifyError(_("Unable to unlock volume"),
_("The installed udisks version does not support the PIM setting"));
}
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED)) if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log(`Unable to mount volume ${volume.get_name()}: ${e.toString()}`); log('Unable to mount volume ' + volume.get_name() + ': ' + e.toString());
this._closeOperation(volume); this._closeOperation(volume);
} }
} }
} },
_onVolumeRemoved(monitor, volume) { _onVolumeRemoved(monitor, volume) {
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) { if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
@@ -224,7 +221,7 @@ var AutomountManager = class {
} }
this._volumeQueue = this._volumeQueue =
this._volumeQueue.filter(element => (element != volume)); this._volumeQueue.filter(element => (element != volume));
} },
_reaskPassword(volume) { _reaskPassword(volume) {
let prevOperation = this._activeOperations.get(volume); let prevOperation = this._activeOperations.get(volume);
@@ -233,7 +230,7 @@ var AutomountManager = class {
new ShellMountOperation.ShellMountOperation(volume, new ShellMountOperation.ShellMountOperation(volume,
{ existingDialog: existingDialog }); { existingDialog: existingDialog });
this._mountVolume(volume, operation); this._mountVolume(volume, operation);
} },
_closeOperation(volume) { _closeOperation(volume) {
let operation = this._activeOperations.get(volume); let operation = this._activeOperations.get(volume);
@@ -241,11 +238,11 @@ var AutomountManager = class {
return; return;
operation.close(); operation.close();
this._activeOperations.delete(volume); this._activeOperations.delete(volume);
} },
_allowAutorun(volume) { _allowAutorun(volume) {
volume.allowAutorun = true; volume.allowAutorun = true;
} },
_allowAutorunExpire(volume) { _allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => { let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
@@ -256,5 +253,5 @@ var AutomountManager = class {
volume._allowAutorunExpireId = id; volume._allowAutorunExpireId = id;
GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun'); GLib.Source.set_name_by_id(id, '[gnome-shell] volume.allowAutorun');
} }
}; });
var Component = AutomountManager; var Component = AutomountManager;

View File

@@ -1,6 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Gio, St } = imports.gi; const Lang = imports.lang;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main; const Main = imports.ui.main;
@@ -40,7 +42,7 @@ function isMountRootHidden(root) {
let path = root.get_path(); let path = root.get_path();
// skip any mounts in hidden directory hierarchies // skip any mounts in hidden directory hierarchies
return (path.includes('/.')); return (path.indexOf('/.') != -1);
} }
function isMountNonLocal(mount) { function isMountNonLocal(mount) {
@@ -65,7 +67,8 @@ function startAppForMount(app, mount) {
retval = app.launch(files, retval = app.launch(files,
global.create_app_launch_context(0, -1)); global.create_app_launch_context(0, -1));
} catch (e) { } catch (e) {
log(`Unable to launch the application ${app.get_name()}: ${e}`); log('Unable to launch the application ' + app.get_name()
+ ': ' + e.toString());
} }
return retval; return retval;
@@ -81,11 +84,13 @@ function HotplugSniffer() {
'/org/gnome/Shell/HotplugSniffer'); '/org/gnome/Shell/HotplugSniffer');
} }
var ContentTypeDiscoverer = class { var ContentTypeDiscoverer = new Lang.Class({
constructor(callback) { Name: 'ContentTypeDiscoverer',
_init(callback) {
this._callback = callback; this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
} },
guessContentTypes(mount) { guessContentTypes(mount) {
let autorunEnabled = !this._settings.get_boolean(SETTING_DISABLE_AUTORUN); let autorunEnabled = !this._settings.get_boolean(SETTING_DISABLE_AUTORUN);
@@ -98,7 +103,7 @@ var ContentTypeDiscoverer = class {
} else { } else {
this._emitCallback(mount, []); this._emitCallback(mount, []);
} }
} },
_onContentTypeGuessed(mount, res) { _onContentTypeGuessed(mount, res) {
let contentTypes = []; let contentTypes = [];
@@ -106,7 +111,8 @@ var ContentTypeDiscoverer = class {
try { try {
contentTypes = mount.guess_content_type_finish(res); contentTypes = mount.guess_content_type_finish(res);
} catch (e) { } catch (e) {
log(`Unable to guess content types on added mount ${mount.get_name()}: ${e}`); log('Unable to guess content types on added mount ' + mount.get_name()
+ ': ' + e.toString());
} }
if (contentTypes.length) { if (contentTypes.length) {
@@ -120,7 +126,7 @@ var ContentTypeDiscoverer = class {
this._emitCallback(mount, contentTypes); this._emitCallback(mount, contentTypes);
}); });
} }
} },
_emitCallback(mount, contentTypes) { _emitCallback(mount, contentTypes) {
if (!contentTypes) if (!contentTypes)
@@ -144,25 +150,27 @@ var ContentTypeDiscoverer = class {
this._callback(mount, apps, contentTypes); this._callback(mount, apps, contentTypes);
} }
}; });
var AutorunManager = class { var AutorunManager = new Lang.Class({
constructor() { Name: 'AutorunManager',
_init() {
this._session = new GnomeSession.SessionManager(); this._session = new GnomeSession.SessionManager();
this._volumeMonitor = Gio.VolumeMonitor.get(); this._volumeMonitor = Gio.VolumeMonitor.get();
this._dispatcher = new AutorunDispatcher(this); this._dispatcher = new AutorunDispatcher(this);
} },
enable() { enable() {
this._mountAddedId = this._volumeMonitor.connect('mount-added', this._onMountAdded.bind(this)); this._mountAddedId = this._volumeMonitor.connect('mount-added', this._onMountAdded.bind(this));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', this._onMountRemoved.bind(this)); this._mountRemovedId = this._volumeMonitor.connect('mount-removed', this._onMountRemoved.bind(this));
} },
disable() { disable() {
this._volumeMonitor.disconnect(this._mountAddedId); this._volumeMonitor.disconnect(this._mountAddedId);
this._volumeMonitor.disconnect(this._mountRemovedId); this._volumeMonitor.disconnect(this._mountRemovedId);
} },
_onMountAdded(monitor, mount) { _onMountAdded(monitor, mount) {
// don't do anything if our session is not the currently // don't do anything if our session is not the currently
@@ -174,35 +182,37 @@ var AutorunManager = class {
this._dispatcher.addMount(mount, apps, contentTypes); this._dispatcher.addMount(mount, apps, contentTypes);
}); });
discoverer.guessContentTypes(mount); discoverer.guessContentTypes(mount);
} },
_onMountRemoved(monitor, mount) { _onMountRemoved(monitor, mount) {
this._dispatcher.removeMount(mount); this._dispatcher.removeMount(mount);
} }
}; });
var AutorunDispatcher = class { var AutorunDispatcher = new Lang.Class({
constructor(manager) { Name: 'AutorunDispatcher',
_init(manager) {
this._manager = manager; this._manager = manager;
this._sources = []; this._sources = [];
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
} },
_getAutorunSettingForType(contentType) { _getAutorunSettingForType(contentType) {
let runApp = this._settings.get_strv(SETTING_START_APP); let runApp = this._settings.get_strv(SETTING_START_APP);
if (runApp.includes(contentType)) if (runApp.indexOf(contentType) != -1)
return AutorunSetting.RUN; return AutorunSetting.RUN;
let ignore = this._settings.get_strv(SETTING_IGNORE); let ignore = this._settings.get_strv(SETTING_IGNORE);
if (ignore.includes(contentType)) if (ignore.indexOf(contentType) != -1)
return AutorunSetting.IGNORE; return AutorunSetting.IGNORE;
let openFiles = this._settings.get_strv(SETTING_OPEN_FOLDER); let openFiles = this._settings.get_strv(SETTING_OPEN_FOLDER);
if (openFiles.includes(contentType)) if (openFiles.indexOf(contentType) != -1)
return AutorunSetting.FILES; return AutorunSetting.FILES;
return AutorunSetting.ASK; return AutorunSetting.ASK;
} },
_getSourceForMount(mount) { _getSourceForMount(mount) {
let filtered = this._sources.filter(source => (source.mount == mount)); let filtered = this._sources.filter(source => (source.mount == mount));
@@ -214,7 +224,7 @@ var AutorunDispatcher = class {
return filtered[0]; return filtered[0];
return null; return null;
} },
_addSource(mount, apps) { _addSource(mount, apps) {
// if we already have a source showing for this // if we already have a source showing for this
@@ -224,7 +234,7 @@ var AutorunDispatcher = class {
// add a new source // add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps)); this._sources.push(new AutorunSource(this._manager, mount, apps));
} },
addMount(mount, apps, contentTypes) { addMount(mount, apps, contentTypes) {
// if autorun is disabled globally, return // if autorun is disabled globally, return
@@ -262,7 +272,7 @@ var AutorunDispatcher = class {
// but we failed launching the default app or the default file manager // but we failed launching the default app or the default file manager
if (!success) if (!success)
this._addSource(mount, apps); this._addSource(mount, apps);
} },
removeMount(mount) { removeMount(mount) {
let source = this._getSourceForMount(mount); let source = this._getSourceForMount(mount);
@@ -274,39 +284,45 @@ var AutorunDispatcher = class {
// destroy the notification source // destroy the notification source
source.destroy(); source.destroy();
} }
}; });
var AutorunSource = class extends MessageTray.Source { var AutorunSource = new Lang.Class({
constructor(manager, mount, apps) { Name: 'AutorunSource',
super(mount.get_name()); Extends: MessageTray.Source,
_init(manager, mount, apps) {
this._manager = manager; this._manager = manager;
this.mount = mount; this.mount = mount;
this.apps = apps; this.apps = apps;
this.parent(mount.get_name());
this._notification = new AutorunNotification(this._manager, this); this._notification = new AutorunNotification(this._manager, this);
// add ourselves as a source, and popup the notification // add ourselves as a source, and popup the notification
Main.messageTray.add(this); Main.messageTray.add(this);
this.notify(this._notification); this.notify(this._notification);
} },
getIcon() { getIcon() {
return this.mount.get_icon(); return this.mount.get_icon();
} },
_createPolicy() { _createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus'); return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
} }
}; });
var AutorunNotification = class extends MessageTray.Notification { var AutorunNotification = new Lang.Class({
constructor(manager, source) { Name: 'AutorunNotification',
super(source, source.title); Extends: MessageTray.Notification,
_init(manager, source) {
this.parent(source, source.title);
this._manager = manager; this._manager = manager;
this._mount = source.mount; this._mount = source.mount;
} },
createBanner() { createBanner() {
let banner = new MessageTray.NotificationBanner(this); let banner = new MessageTray.NotificationBanner(this);
@@ -319,7 +335,7 @@ var AutorunNotification = class extends MessageTray.Notification {
}); });
return banner; return banner;
} },
_buttonForApp(app) { _buttonForApp(app) {
let box = new St.BoxLayout(); let box = new St.BoxLayout();
@@ -346,14 +362,14 @@ var AutorunNotification = class extends MessageTray.Notification {
}); });
return button; return button;
} },
activate() { activate() {
super.activate(); this.parent();
let app = Gio.app_info_get_default_for_type('inode/directory', false); let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount); startAppForMount(app, this._mount);
} }
}; });
var Component = AutorunManager; var Component = AutorunManager;

View File

@@ -1,19 +1,31 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi; const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gcr = imports.gi.Gcr;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const CheckBox = imports.ui.checkBox; const CheckBox = imports.ui.checkBox;
const Tweener = imports.ui.tweener;
var WORK_SPINNER_ICON_SIZE = 16; var WORK_SPINNER_ICON_SIZE = 16;
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
var WORK_SPINNER_ANIMATION_TIME = 0.3;
var KeyringDialog = new Lang.Class({
Name: 'KeyringDialog',
Extends: ModalDialog.ModalDialog,
var KeyringDialog = GObject.registerClass(
class KeyringDialog extends ModalDialog.ModalDialog {
_init() { _init() {
super._init({ styleClass: 'prompt-dialog' }); this.parent({ styleClass: 'prompt-dialog' });
this.prompt = new Shell.KeyringPrompt(); this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', this._onShowPassword.bind(this)); this.prompt.connect('show-password', this._onShowPassword.bind(this));
@@ -24,8 +36,20 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this._content = new Dialog.MessageDialogContent({ icon }); this._content = new Dialog.MessageDialogContent({ icon });
this.contentLayout.add(this._content); this.contentLayout.add(this._content);
// FIXME: Why does this break now?
/*
this.prompt.bind_property('message', this._content, 'title', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('message', this._content, 'title', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('description', this._content, 'body', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('description', this._content, 'body', GObject.BindingFlags.SYNC_CREATE);
*/
this.prompt.connect('notify::message', () => {
this._content.title = this.prompt.message;
});
this._content.title = this.prompt.message;
this.prompt.connect('notify::description', () => {
this._content.body = this.prompt.description;
});
this._content.body = this.prompt.description;
this._workSpinner = null; this._workSpinner = null;
this._controlTable = null; this._controlTable = null;
@@ -39,17 +63,34 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
} },
_setWorking(working) { _setWorking(working) {
if (!this._workSpinner) if (!this._workSpinner)
return; return;
if (working) Tweener.removeTweens(this._workSpinner.actor);
if (working) {
this._workSpinner.play(); this._workSpinner.play();
else Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (this._workSpinner)
this._workSpinner.stop(); this._workSpinner.stop();
} }
});
}
},
_buildControlTable() { _buildControlTable() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
@@ -73,7 +114,9 @@ class KeyringDialog extends ModalDialog.ModalDialog {
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this)); this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true); let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
if (rtl) { if (rtl) {
layout.attach(this._workSpinner.actor, 0, row, 1, 1); layout.attach(this._workSpinner.actor, 0, row, 1, 1);
@@ -140,7 +183,7 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this._controlTable = table; this._controlTable = table;
this._content.messageBox.add(table, { x_fill: true, y_fill: true }); this._content.messageBox.add(table, { x_fill: true, y_fill: true });
} },
_updateSensitivity(sensitive) { _updateSensitivity(sensitive) {
if (this._passwordEntry) { if (this._passwordEntry) {
@@ -156,7 +199,7 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this._continueButton.can_focus = sensitive; this._continueButton.can_focus = sensitive;
this._continueButton.reactive = sensitive; this._continueButton.reactive = sensitive;
this._setWorking(!sensitive); this._setWorking(!sensitive);
} },
_ensureOpen() { _ensureOpen() {
// NOTE: ModalDialog.open() is safe to call if the dialog is // NOTE: ModalDialog.open() is safe to call if the dialog is
@@ -172,63 +215,67 @@ class KeyringDialog extends ModalDialog.ModalDialog {
log('keyringPrompt: Failed to show modal dialog.' + log('keyringPrompt: Failed to show modal dialog.' +
' Dismissing prompt request'); ' Dismissing prompt request');
this.prompt.cancel(); this.prompt.cancel()
return false; return false;
} },
_onShowPassword(prompt) { _onShowPassword(prompt) {
this._buildControlTable(); this._buildControlTable();
this._ensureOpen(); this._ensureOpen();
this._updateSensitivity(true); this._updateSensitivity(true);
this._passwordEntry.grab_key_focus(); this._passwordEntry.grab_key_focus();
} },
_onShowConfirm(prompt) { _onShowConfirm(prompt) {
this._buildControlTable(); this._buildControlTable();
this._ensureOpen(); this._ensureOpen();
this._updateSensitivity(true); this._updateSensitivity(true);
this._continueButton.grab_key_focus(); this._continueButton.grab_key_focus();
} },
_onHidePrompt(prompt) { _onHidePrompt(prompt) {
this.close(); this.close();
} },
_onPasswordActivate() { _onPasswordActivate() {
if (this.prompt.confirm_visible) if (this.prompt.confirm_visible)
this._confirmEntry.grab_key_focus(); this._confirmEntry.grab_key_focus();
else else
this._onContinueButton(); this._onContinueButton();
} },
_onConfirmActivate() { _onConfirmActivate() {
this._onContinueButton(); this._onContinueButton();
} },
_onContinueButton() { _onContinueButton() {
this._updateSensitivity(false); this._updateSensitivity(false);
this.prompt.complete(); this.prompt.complete();
} },
_onCancelButton() { _onCancelButton() {
this.prompt.cancel(); this.prompt.cancel();
} },
}); });
var KeyringDummyDialog = class { var KeyringDummyDialog = new Lang.Class({
constructor() { Name: 'KeyringDummyDialog',
_init() {
this.prompt = new Shell.KeyringPrompt(); this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', this._cancelPrompt.bind(this)); this.prompt.connect('show-password', this._cancelPrompt.bind(this));
this.prompt.connect('show-confirm', this._cancelPrompt.bind(this)); this.prompt.connect('show-confirm', this._cancelPrompt.bind(this));
} },
_cancelPrompt() { _cancelPrompt() {
this.prompt.cancel(); this.prompt.cancel();
} }
}; });
var KeyringPrompter = class { var KeyringPrompter = new Lang.Class({
constructor() { Name: 'KeyringPrompter',
_init() {
this._prompter = new Gcr.SystemPrompter(); this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', () => { this._prompter.connect('new-prompt', () => {
let dialog = this._enabled ? new KeyringDialog() let dialog = this._enabled ? new KeyringDialog()
@@ -240,7 +287,7 @@ var KeyringPrompter = class {
this._registered = false; this._registered = false;
this._enabled = false; this._enabled = false;
this._currentPrompt = null; this._currentPrompt = null;
} },
enable() { enable() {
if (!this._registered) { if (!this._registered) {
@@ -250,7 +297,7 @@ var KeyringPrompter = class {
this._registered = true; this._registered = true;
} }
this._enabled = true; this._enabled = true;
} },
disable() { disable() {
this._enabled = false; this._enabled = false;
@@ -259,6 +306,6 @@ var KeyringPrompter = class {
this._currentPrompt.cancel(); this._currentPrompt.cancel();
this._currentPrompt = null; this._currentPrompt = null;
} }
}; });
var Component = KeyringPrompter; var Component = KeyringPrompter;

View File

@@ -1,21 +1,32 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, GObject, NM, Pango, 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 Lang = imports.lang;
const NM = imports.gi.NM;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St;
const Config = imports.misc.config; const Config = imports.misc.config;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const PopupMenu = imports.ui.popupMenu;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const VPN_UI_GROUP = 'VPN Plugin UI'; const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = GObject.registerClass( var NetworkSecretDialog = new Lang.Class({
class NetworkSecretDialog extends ModalDialog.ModalDialog { Name: 'NetworkSecretDialog',
_init(agent, requestId, connection, settingName, hints, flags, contentOverride) { Extends: ModalDialog.ModalDialog,
super._init({ styleClass: 'prompt-dialog' });
_init(agent, requestId, connection, settingName, hints, contentOverride) {
this.parent({ styleClass: 'prompt-dialog' });
this._agent = agent; this._agent = agent;
this._requestId = requestId; this._requestId = requestId;
@@ -80,9 +91,8 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
secret.valid = secret.value.length > 0; secret.valid = secret.value.length > 0;
this._updateOkButton(); this._updateOkButton();
}); });
} else { } else
secret.valid = true; secret.valid = true;
}
if (rtl) { if (rtl) {
layout.attach(secret.entry, 0, pos, 1, 1); layout.attach(secret.entry, 0, pos, 1, 1);
@@ -99,18 +109,6 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
contentBox.messageBox.add(secretTable); contentBox.messageBox.add(secretTable);
if (flags & NM.SecretAgentGetSecretsFlags.WPS_PBC_ACTIVE) {
let descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
text: _("Alternatively you can connect by pushing the “WPS” button on your router.") });
descriptionLabel.clutter_text.line_wrap = true;
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
contentBox.messageBox.add(descriptionLabel,
{ y_fill: true,
y_align: St.Align.START,
expand: true });
}
this._okButton = { label: _("Connect"), this._okButton = { label: _("Connect"),
action: this._onOk.bind(this), action: this._onOk.bind(this),
default: true default: true
@@ -123,7 +121,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._okButton]); this._okButton]);
this._updateOkButton(); this._updateOkButton();
} },
_updateOkButton() { _updateOkButton() {
let valid = true; let valid = true;
@@ -134,7 +132,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._okButton.button.reactive = valid; this._okButton.button.reactive = valid;
this._okButton.button.can_focus = valid; this._okButton.button.can_focus = valid;
} },
_onOk() { _onOk() {
let valid = true; let valid = true;
@@ -150,12 +148,12 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this.close(global.get_current_time()); this.close(global.get_current_time());
} }
// do nothing if not valid // do nothing if not valid
} },
cancel() { cancel() {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
this.close(global.get_current_time()); this.close(global.get_current_time());
} },
_validateWpaPsk(secret) { _validateWpaPsk(secret) {
let value = secret.value; let value = secret.value;
@@ -171,7 +169,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
} }
return (value.length >= 8 && value.length <= 63); return (value.length >= 8 && value.length <= 63);
} },
_validateStaticWep(secret) { _validateStaticWep(secret) {
let value = secret.value; let value = secret.value;
@@ -189,15 +187,14 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
|| (value[i] >= 'A' && value[i] <= 'Z'))) || (value[i] >= 'A' && value[i] <= 'Z')))
return false; return false;
} }
} else { } else
return false; return false;
}
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) { } else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
if (value.length < 0 || value.length > 64) if (value.length < 0 || value.length > 64)
return false; return false;
} }
return true; return true;
} },
_getWirelessSecrets(secrets, wirelessSetting) { _getWirelessSecrets(secrets, wirelessSetting) {
let wirelessSecuritySetting = this._connection.get_setting_wireless_security(); let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
@@ -216,7 +213,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
validate: this._validateWpaPsk, password: true }); validate: this._validateWpaPsk, password: true });
break; break;
case 'none': // static WEP case 'none': // static WEP
secrets.push({ label: _("Key: "), key: `wep-key${wirelessSecuritySetting.wep_tx_keyidx}`, secrets.push({ label: _("Key: "), key: 'wep-key' + wirelessSecuritySetting.wep_tx_keyidx,
value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '', value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
wep_key_type: wirelessSecuritySetting.wep_key_type, wep_key_type: wirelessSecuritySetting.wep_key_type,
validate: this._validateStaticWep, password: true }); validate: this._validateStaticWep, password: true });
@@ -232,12 +229,13 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._get8021xSecrets(secrets); this._get8021xSecrets(secrets);
break; break;
default: default:
log(`Invalid wireless key management: ${wirelessSecuritySetting.key_mgmt}`); log('Invalid wireless key management: ' + wirelessSecuritySetting.key_mgmt);
}
} }
},
_get8021xSecrets(secrets) { _get8021xSecrets(secrets) {
let ieee8021xSetting = this._connection.get_setting_802_1x(); let ieee8021xSetting = this._connection.get_setting_802_1x();
let phase2method;
/* If hints were given we know exactly what we need to ask */ /* If hints were given we know exactly what we need to ask */
if (this._settingName == "802-1x" && this._hints.length) { if (this._settingName == "802-1x" && this._hints.length) {
@@ -274,9 +272,9 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
value: ieee8021xSetting.private_key_password || '', password: true }); value: ieee8021xSetting.private_key_password || '', password: true });
break; break;
default: default:
log(`Invalid EAP/IEEE802.1x method: ${ieee8021xSetting.get_eap_method(0)}`); log('Invalid EAP/IEEE802.1x method: ' + ieee8021xSetting.get_eap_method(0));
}
} }
},
_getPPPoESecrets(secrets) { _getPPPoESecrets(secrets) {
let pppoeSetting = this._connection.get_setting_pppoe(); let pppoeSetting = this._connection.get_setting_pppoe();
@@ -286,7 +284,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
value: pppoeSetting.service || '', password: false }); value: pppoeSetting.service || '', password: false });
secrets.push({ label: _("Password: "), key: 'password', secrets.push({ label: _("Password: "), key: 'password',
value: pppoeSetting.password || '', password: true }); value: pppoeSetting.password || '', password: true });
} },
_getMobileSecrets(secrets, connectionType) { _getMobileSecrets(secrets, connectionType) {
let setting; let setting;
@@ -296,7 +294,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
setting = this._connection.get_setting_by_name(connectionType); setting = this._connection.get_setting_by_name(connectionType);
secrets.push({ label: _("Password: "), key: 'password', secrets.push({ label: _("Password: "), key: 'password',
value: setting.value || '', password: true }); value: setting.value || '', password: true });
} },
_getContent() { _getContent() {
let connectionSetting = this._connection.get_setting_connection(); let connectionSetting = this._connection.get_setting_connection();
@@ -305,7 +303,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
let ssid; let ssid;
let content = { }; let content = { };
content.secrets = []; content.secrets = [ ];
switch (connectionType) { switch (connectionType) {
case '802-11-wireless': case '802-11-wireless':
@@ -328,7 +326,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._getPPPoESecrets(content.secrets); this._getPPPoESecrets(content.secrets);
break; break;
case 'gsm': case 'gsm':
if (this._hints.includes('pin')) { if (this._hints.indexOf('pin') != -1) {
let gsmSetting = this._connection.get_setting_gsm(); let gsmSetting = this._connection.get_setting_gsm();
content.title = _("PIN code required"); content.title = _("PIN code required");
content.message = _("PIN code is needed for the mobile broadband device"); content.message = _("PIN code is needed for the mobile broadband device");
@@ -344,31 +342,33 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
this._getMobileSecrets(content.secrets, connectionType); this._getMobileSecrets(content.secrets, connectionType);
break; break;
default: default:
log(`Invalid connection type: ${connectionType}`); log('Invalid connection type: ' + connectionType);
} };
return content; return content;
} }
}); });
var VPNRequestHandler = class { var VPNRequestHandler = new Lang.Class({
constructor(agent, requestId, authHelper, serviceType, connection, hints, flags) { Name: 'VPNRequestHandler',
_init(agent, requestId, authHelper, serviceType, connection, hints, flags) {
this._agent = agent; this._agent = agent;
this._requestId = requestId; this._requestId = requestId;
this._connection = connection; this._connection = connection;
this._flags = flags;
this._pluginOutBuffer = []; this._pluginOutBuffer = [];
this._title = null; this._title = null;
this._description = null; this._description = null;
this._content = []; this._content = [ ];
this._shellDialog = null; this._shellDialog = null;
let connectionSetting = connection.get_setting_connection(); let connectionSetting = connection.get_setting_connection();
let argv = [authHelper.fileName, let argv = [ authHelper.fileName,
'-u', connectionSetting.uuid, '-u', connectionSetting.uuid,
'-n', connectionSetting.id, '-n', connectionSetting.id,
'-s', serviceType]; '-s', serviceType
];
if (authHelper.externalUIMode) if (authHelper.externalUIMode)
argv.push('--external-ui-mode'); argv.push('--external-ui-mode');
if (flags & NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION) if (flags & NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
@@ -407,12 +407,12 @@ var VPNRequestHandler = class {
this._vpnChildFinished.bind(this)); this._vpnChildFinished.bind(this));
this._writeConnection(); this._writeConnection();
} catch (e) { } catch(e) {
logError(e, 'error while spawning VPN auth helper'); logError(e, 'error while spawning VPN auth helper');
this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
} }
} },
cancel(respond) { cancel(respond) {
if (respond) if (respond)
@@ -424,11 +424,11 @@ var VPNRequestHandler = class {
} else { } else {
try { try {
this._stdin.write('QUIT\n\n', null); this._stdin.write('QUIT\n\n', null);
} catch (e) { /* ignore broken pipe errors */ } } catch(e) { /* ignore broken pipe errors */ }
} }
this.destroy(); this.destroy();
} },
destroy() { destroy() {
if (this._destroyed) if (this._destroyed)
@@ -442,7 +442,7 @@ var VPNRequestHandler = class {
// Stdout is closed when we finish reading from it // Stdout is closed when we finish reading from it
this._destroyed = true; this._destroyed = true;
} },
_vpnChildFinished(pid, status, requestObj) { _vpnChildFinished(pid, status, requestObj) {
this._childWatch = 0; this._childWatch = 0;
@@ -459,12 +459,11 @@ var VPNRequestHandler = class {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
else else
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
} else { } else
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
}
this.destroy(); this.destroy();
} },
_vpnChildProcessLineOldStyle(line) { _vpnChildProcessLineOldStyle(line) {
if (this._previousLine != undefined) { if (this._previousLine != undefined) {
@@ -474,7 +473,7 @@ var VPNRequestHandler = class {
if (line == '' && this._previousLine == '') { if (line == '' && this._previousLine == '') {
try { try {
this._stdin.write('QUIT\n\n', null); this._stdin.write('QUIT\n\n', null);
} catch (e) { /* ignore broken pipe errors */ } } catch(e) { /* ignore broken pipe errors */ }
} else { } else {
this._agent.set_password(this._requestId, this._previousLine, line); this._agent.set_password(this._requestId, this._previousLine, line);
this._previousLine = undefined; this._previousLine = undefined;
@@ -482,7 +481,7 @@ var VPNRequestHandler = class {
} else { } else {
this._previousLine = line; this._previousLine = line;
} }
} },
_readStdoutOldStyle() { _readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => { this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
@@ -499,7 +498,7 @@ var VPNRequestHandler = class {
// try to read more! // try to read more!
this._readStdoutOldStyle(); this._readStdoutOldStyle();
}); });
} },
_readStdoutNewStyle() { _readStdoutNewStyle() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => { this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
@@ -517,7 +516,7 @@ var VPNRequestHandler = class {
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size()); this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle(); this._readStdoutNewStyle();
}); });
} },
_showNewStyleDialog() { _showNewStyleDialog() {
let keyfile = new GLib.KeyFile(); let keyfile = new GLib.KeyFile();
@@ -562,7 +561,7 @@ var VPNRequestHandler = class {
this._agent.set_password(this._requestId, groups[i], value); this._agent.set_password(this._requestId, groups[i], value);
} }
} }
} catch (e) { } catch(e) {
// No output is a valid case it means "both secrets are stored" // No output is a valid case it means "both secrets are stored"
if (data.length > 0) { if (data.length > 0) {
logError(e, 'error while reading VPN plugin output keyfile'); logError(e, 'error while reading VPN plugin output keyfile');
@@ -575,39 +574,41 @@ var VPNRequestHandler = class {
if (contentOverride && contentOverride.secrets.length) { if (contentOverride && contentOverride.secrets.length) {
// Only show the dialog if we actually have something to ask // Only show the dialog if we actually have something to ask
this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], this._flags, contentOverride); this._shellDialog = new NetworkSecretDialog(this._agent, this._requestId, this._connection, 'vpn', [], contentOverride);
this._shellDialog.open(global.get_current_time()); this._shellDialog.open(global.get_current_time());
} else { } else {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
this.destroy(); this.destroy();
} }
} },
_writeConnection() { _writeConnection() {
let vpnSetting = this._connection.get_setting_vpn(); let vpnSetting = this._connection.get_setting_vpn();
try { try {
vpnSetting.foreach_data_item((key, value) => { vpnSetting.foreach_data_item((key, value) => {
this._stdin.write(`DATA_KEY=${key}\n`, null); this._stdin.write('DATA_KEY=' + key + '\n', null);
this._stdin.write(`DATA_VAL=${value || ''}\n\n`, null); this._stdin.write('DATA_VAL=' + (value || '') + '\n\n', null);
}); });
vpnSetting.foreach_secret((key, value) => { vpnSetting.foreach_secret((key, value) => {
this._stdin.write(`SECRET_KEY=${key}\n`, null); this._stdin.write('SECRET_KEY=' + key + '\n', null);
this._stdin.write(`SECRET_VAL=${value || ''}\n\n`, null); this._stdin.write('SECRET_VAL=' + (value || '') + '\n\n', null);
}); });
this._stdin.write('DONE\n\n', null); this._stdin.write('DONE\n\n', null);
} catch (e) { } catch(e) {
logError(e, 'internal error while writing connection to helper'); logError(e, 'internal error while writing connection to helper');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
this.destroy(); this.destroy();
} }
} },
}; });
Signals.addSignalMethods(VPNRequestHandler.prototype); Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = class { var NetworkAgent = new Lang.Class({
constructor() { Name: 'NetworkAgent',
_init() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent', this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS, capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false auto_register: false
@@ -620,9 +621,9 @@ var NetworkAgent = class {
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR); this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try { try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null); let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => this._vpnCacheBuilt = false); monitor.connect('changed', () => { this._vpnCacheBuilt = false; });
} catch (e) { } catch(e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`); log('Failed to create monitor for VPN plugin dir: ' + e.message);
} }
this._native.connect('new-request', this._newRequest.bind(this)); this._native.connect('new-request', this._newRequest.bind(this));
@@ -633,12 +634,12 @@ var NetworkAgent = class {
try { try {
this._native.init_finish(res); this._native.init_finish(res);
this._initialized = true; this._initialized = true;
} catch (e) { } catch(e) {
this._native = null; this._native = null;
logError(e, 'error initializing the NetworkManager Agent'); logError(e, 'error initializing the NetworkManager Agent');
} }
}); });
} },
enable() { enable() {
if (!this._native) if (!this._native)
@@ -647,7 +648,7 @@ var NetworkAgent = class {
this._native.auto_register = true; this._native.auto_register = true;
if (this._initialized && !this._native.registered) if (this._initialized && !this._native.registered)
this._native.register_async(null, null); this._native.register_async(null, null);
} },
disable() { disable() {
let requestId; let requestId;
@@ -670,7 +671,7 @@ var NetworkAgent = class {
this._native.auto_register = false; this._native.auto_register = false;
if (this._initialized && this._native.registered) if (this._initialized && this._native.registered)
this._native.unregister_async(null, null); this._native.unregister_async(null, null);
} },
_showNotification(requestId, connection, settingName, hints, flags) { _showNotification(requestId, connection, settingName, hints, flags) {
let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive'); let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive');
@@ -681,13 +682,12 @@ var NetworkAgent = class {
let connectionSetting = connection.get_setting_connection(); let connectionSetting = connection.get_setting_connection();
let connectionType = connectionSetting.get_connection_type(); let connectionType = connectionSetting.get_connection_type();
switch (connectionType) { switch (connectionType) {
case '802-11-wireless': { case '802-11-wireless':
let wirelessSetting = connection.get_setting_wireless(); let wirelessSetting = connection.get_setting_wireless();
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data()); let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
title = _("Authentication required by wireless network"); title = _("Authentication required by wireless network");
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid); body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
break; break;
}
case '802-3-ethernet': case '802-3-ethernet':
title = _("Wired 802.1X authentication"); title = _("Wired 802.1X authentication");
body = _("A password is required to connect to “%s”.".format(connection.get_id())); body = _("A password is required to connect to “%s”.".format(connection.get_id()));
@@ -697,19 +697,20 @@ var NetworkAgent = class {
body = _("A password is required to connect to “%s”.".format(connection.get_id())); body = _("A password is required to connect to “%s”.".format(connection.get_id()));
break; break;
case 'gsm': case 'gsm':
if (hints.includes('pin')) { if (hints.indexOf('pin') != -1) {
let gsmSetting = connection.get_setting_gsm();
title = _("PIN code required"); title = _("PIN code required");
body = _("PIN code is needed for the mobile broadband device"); message = _("PIN code is needed for the mobile broadband device");
break; break;
} }
// fall through // fall through
case 'cdma': case 'cdma':
case 'bluetooth': case 'bluetooth':
title = _("Mobile broadband network password"); title = _("Mobile broadband network password");
body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id()); message = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
break; break;
default: default:
log(`Invalid connection type: ${connectionType}`); log('Invalid connection type: ' + connectionType);
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR); this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
return; return;
} }
@@ -730,14 +731,14 @@ var NetworkAgent = class {
Main.messageTray.add(source); Main.messageTray.add(source);
source.notify(notification); source.notify(notification);
} },
_newRequest(agent, requestId, connection, settingName, hints, flags) { _newRequest(agent, requestId, connection, settingName, hints, flags) {
if (!(flags & NM.SecretAgentGetSecretsFlags.USER_REQUESTED)) if (!(flags & NM.SecretAgentGetSecretsFlags.USER_REQUESTED))
this._showNotification(requestId, connection, settingName, hints, flags); this._showNotification(requestId, connection, settingName, hints, flags);
else else
this._handleRequest(requestId, connection, settingName, hints, flags); this._handleRequest(requestId, connection, settingName, hints, flags);
} },
_handleRequest(requestId, connection, settingName, hints, flags) { _handleRequest(requestId, connection, settingName, hints, flags) {
if (settingName == 'vpn') { if (settingName == 'vpn') {
@@ -745,13 +746,13 @@ var NetworkAgent = class {
return; return;
} }
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints, flags); let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints);
dialog.connect('destroy', () => { dialog.connect('destroy', () => {
delete this._dialogs[requestId]; delete this._dialogs[requestId];
}); });
this._dialogs[requestId] = dialog; this._dialogs[requestId] = dialog;
dialog.open(global.get_current_time()); dialog.open(global.get_current_time());
} },
_cancelRequest(agent, requestId) { _cancelRequest(agent, requestId) {
if (this._dialogs[requestId]) { if (this._dialogs[requestId]) {
@@ -762,7 +763,7 @@ var NetworkAgent = class {
this._vpnRequests[requestId].cancel(false); this._vpnRequests[requestId].cancel(false);
delete this._vpnRequests[requestId]; delete this._vpnRequests[requestId];
} }
} },
_vpnRequest(requestId, connection, hints, flags) { _vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn(); let vpnSetting = connection.get_setting_vpn();
@@ -784,7 +785,7 @@ var NetworkAgent = class {
delete this._vpnRequests[requestId]; delete this._vpnRequests[requestId];
}); });
this._vpnRequests[requestId] = vpnRequest; this._vpnRequests[requestId] = vpnRequest;
} },
_buildVPNServiceCache() { _buildVPNServiceCache() {
if (this._vpnCacheBuilt) if (this._vpnCacheBuilt)
@@ -817,5 +818,5 @@ var NetworkAgent = class {
} }
}); });
} }
}; });
var Component = NetworkAgent; var Component = NetworkAgent;

View File

@@ -1,24 +1,39 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { AccountsService, Clutter, Gio, GLib, const Lang = imports.lang;
GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi; const Signals = imports.signals;
const Shell = imports.gi.Shell;
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Polkit = imports.gi.Polkit;
const PolkitAgent = imports.gi.PolkitAgent;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Components = imports.ui.components;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const Main = imports.ui.main; const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
const Tweener = imports.ui.tweener;
var DIALOG_ICON_SIZE = 48; var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16; var WORK_SPINNER_ICON_SIZE = 16;
var WORK_SPINNER_ANIMATION_DELAY = 1.0;
var WORK_SPINNER_ANIMATION_TIME = 0.3;
var AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
Extends: ModalDialog.ModalDialog,
var AuthenticationDialog = GObject.registerClass({
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } }
}, class AuthenticationDialog extends ModalDialog.ModalDialog {
_init(actionId, body, cookie, userNames) { _init(actionId, body, cookie, userNames) {
super._init({ styleClass: 'prompt-dialog' }); this.parent({ styleClass: 'prompt-dialog' });
this.actionId = actionId; this.actionId = actionId;
this.message = body; this.message = body;
@@ -26,11 +41,9 @@ var AuthenticationDialog = GObject.registerClass({
this._wasDismissed = false; this._wasDismissed = false;
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => { this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
this.visible = !Main.sessionMode.isLocked; this._group.visible = !Main.sessionMode.isLocked;
}); });
this.connect('closed', this._onDialogClosed.bind(this));
let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' }); let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
let title = _("Authentication Required"); let title = _("Authentication Required");
@@ -38,19 +51,19 @@ var AuthenticationDialog = GObject.registerClass({
this.contentLayout.add_actor(content); this.contentLayout.add_actor(content);
if (userNames.length > 1) { if (userNames.length > 1) {
log(`polkitAuthenticationAgent: Received ${userNames.length} ` + log('polkitAuthenticationAgent: Received ' + userNames.length +
'identities that can be used for authentication. Only ' + ' identities that can be used for authentication. Only ' +
'considering one.'); 'considering one.');
} }
let userName = GLib.get_user_name(); let userName = GLib.get_user_name();
if (!userNames.includes(userName)) if (userNames.indexOf(userName) < 0)
userName = 'root'; userName = 'root';
if (!userNames.includes(userName)) if (userNames.indexOf(userName) < 0)
userName = userNames[0]; userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName); this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name(); let userRealName = this._user.get_real_name()
this._userLoadedId = this._user.connect('notify::is_loaded', this._userLoadedId = this._user.connect('notify::is_loaded',
this._onUserChanged.bind(this)); this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed', this._userChangedId = this._user.connect('changed',
@@ -98,13 +111,16 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE }); this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry', this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: "", text: "",
can_focus: true }); can_focus: true});
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this)); this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
this._passwordBox.add(this._passwordEntry, this._passwordBox.add(this._passwordEntry,
{ expand: true }); { expand: true });
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true); let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
this._workSpinner.actor.opacity = 0;
this._passwordBox.add(this._workSpinner.actor); this._passwordBox.add(this._workSpinner.actor);
this.setInitialKeyFocus(this._passwordEntry); this.setInitialKeyFocus(this._passwordEntry);
@@ -127,7 +143,7 @@ var AuthenticationDialog = GObject.registerClass({
* gnome-shell.css sets the color to be transparent * gnome-shell.css sets the color to be transparent
*/ */
this._nullMessageLabel = new St.Label({ style_class: 'prompt-dialog-null-label', this._nullMessageLabel = new St.Label({ style_class: 'prompt-dialog-null-label',
text: 'abc' }); text: 'abc'});
this._nullMessageLabel.add_style_class_name('hidden'); this._nullMessageLabel.add_style_class_name('hidden');
this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._nullMessageLabel.clutter_text.line_wrap = true; this._nullMessageLabel.clutter_text.line_wrap = true;
@@ -145,25 +161,50 @@ var AuthenticationDialog = GObject.registerClass({
this._identityToAuth = Polkit.UnixUser.new_for_name(userName); this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
this._cookie = cookie; this._cookie = cookie;
} },
_setWorking(working) { _setWorking(working) {
if (working) Tweener.removeTweens(this._workSpinner.actor);
if (working) {
this._workSpinner.play(); this._workSpinner.play();
else Tweener.addTween(this._workSpinner.actor,
{ opacity: 255,
delay: WORK_SPINNER_ANIMATION_DELAY,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear'
});
} else {
Tweener.addTween(this._workSpinner.actor,
{ opacity: 0,
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (this._workSpinner)
this._workSpinner.stop(); this._workSpinner.stop();
} }
});
}
},
performAuthentication() { performAuthentication() {
this._destroySession(); this.destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth, this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie }); cookie: this._cookie });
this._sessionCompletedId = this._session.connect('completed', this._onSessionCompleted.bind(this)); this._session.connect('completed', this._onSessionCompleted.bind(this));
this._sessionRequestId = this._session.connect('request', this._onSessionRequest.bind(this)); this._session.connect('request', this._onSessionRequest.bind(this));
this._sessionShowErrorId = this._session.connect('show-error', this._onSessionShowError.bind(this)); this._session.connect('show-error', this._onSessionShowError.bind(this));
this._sessionShowInfoId = this._session.connect('show-info', this._onSessionShowInfo.bind(this)); this._session.connect('show-info', this._onSessionShowInfo.bind(this));
this._session.initiate(); this._session.initiate();
} },
close(timestamp) {
this.parent(timestamp);
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
},
_ensureOpen() { _ensureOpen() {
// NOTE: ModalDialog.open() is safe to call if the dialog is // NOTE: ModalDialog.open() is safe to call if the dialog is
@@ -180,19 +221,19 @@ var AuthenticationDialog = GObject.registerClass({
// //
// We could add retrying if this turns out to be a problem // We could add retrying if this turns out to be a problem
log('polkitAuthenticationAgent: Failed to show modal dialog. ' + log('polkitAuthenticationAgent: Failed to show modal dialog.' +
`Dismissing authentication request for action-id ${this.actionId} ` + ' Dismissing authentication request for action-id ' + this.actionId +
`cookie ${this._cookie}`); ' cookie ' + this._cookie);
this._emitDone(true); this._emitDone(true);
} }
} },
_emitDone(dismissed) { _emitDone(dismissed) {
if (!this._doneEmitted) { if (!this._doneEmitted) {
this._doneEmitted = true; this._doneEmitted = true;
this.emit('done', dismissed); this.emit('done', dismissed);
} }
} },
_updateSensitivity(sensitive) { _updateSensitivity(sensitive) {
this._passwordEntry.reactive = sensitive; this._passwordEntry.reactive = sensitive;
@@ -201,7 +242,7 @@ var AuthenticationDialog = GObject.registerClass({
this._okButton.can_focus = sensitive; this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive; this._okButton.reactive = sensitive;
this._setWorking(!sensitive); this._setWorking(!sensitive);
} },
_onEntryActivate() { _onEntryActivate() {
let response = this._passwordEntry.get_text(); let response = this._passwordEntry.get_text();
@@ -212,11 +253,11 @@ var AuthenticationDialog = GObject.registerClass({
this._errorMessageLabel.hide(); this._errorMessageLabel.hide();
this._infoMessageLabel.hide(); this._infoMessageLabel.hide();
this._nullMessageLabel.show(); this._nullMessageLabel.show();
} },
_onAuthenticateButtonPressed() { _onAuthenticateButtonPressed() {
this._onEntryActivate(); this._onEntryActivate();
} },
_onSessionCompleted(session, gainedAuthorization) { _onSessionCompleted(session, gainedAuthorization) {
if (this._completed || this._doneEmitted) if (this._completed || this._doneEmitted)
@@ -248,16 +289,16 @@ var AuthenticationDialog = GObject.registerClass({
/* Try and authenticate again */ /* Try and authenticate again */
this.performAuthentication(); this.performAuthentication();
} }
} },
_onSessionRequest(session, request, echoOn) { _onSessionRequest(session, request, echo_on) {
// Cheap localization trick // Cheap localization trick
if (request == 'Password:' || request == 'Password: ') if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:")); this._passwordLabel.set_text(_("Password:"));
else else
this._passwordLabel.set_text(request); this._passwordLabel.set_text(request);
if (echoOn) if (echo_on)
this._passwordEntry.clutter_text.set_password_char(''); this._passwordEntry.clutter_text.set_password_char('');
else else
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
@@ -267,7 +308,7 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordEntry.grab_key_focus(); this._passwordEntry.grab_key_focus();
this._updateSensitivity(true); this._updateSensitivity(true);
this._ensureOpen(); this._ensureOpen();
} },
_onSessionShowError(session, text) { _onSessionShowError(session, text) {
this._passwordEntry.set_text(''); this._passwordEntry.set_text('');
@@ -276,7 +317,7 @@ var AuthenticationDialog = GObject.registerClass({
this._infoMessageLabel.hide(); this._infoMessageLabel.hide();
this._nullMessageLabel.hide(); this._nullMessageLabel.hide();
this._ensureOpen(); this._ensureOpen();
} },
_onSessionShowInfo(session, text) { _onSessionShowInfo(session, text) {
this._passwordEntry.set_text(''); this._passwordEntry.set_text('');
@@ -285,75 +326,59 @@ var AuthenticationDialog = GObject.registerClass({
this._errorMessageLabel.hide(); this._errorMessageLabel.hide();
this._nullMessageLabel.hide(); this._nullMessageLabel.hide();
this._ensureOpen(); this._ensureOpen();
} },
_destroySession() { destroySession() {
if (this._session) { if (this._session) {
if (!this._completed) if (!this._completed)
this._session.cancel(); this._session.cancel();
this._completed = false; this._completed = false;
this._session.disconnect(this._sessionCompletedId);
this._session.disconnect(this._sessionRequestId);
this._session.disconnect(this._sessionShowErrorId);
this._session.disconnect(this._sessionShowInfoId);
this._session = null; this._session = null;
} }
} },
_onUserChanged() { _onUserChanged() {
if (this._user.is_loaded && this._userAvatar) { if (this._user.is_loaded && this._userAvatar) {
this._userAvatar.update(); this._userAvatar.update();
this._userAvatar.actor.show(); this._userAvatar.actor.show();
} }
} },
cancel() { cancel() {
this._wasDismissed = true; this._wasDismissed = true;
this.close(global.get_current_time()); this.close(global.get_current_time());
this._emitDone(true); this._emitDone(true);
} },
_onDialogClosed() {
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
if (this._user) {
this._user.disconnect(this._userLoadedId);
this._user.disconnect(this._userChangedId);
this._user = null;
}
this._destroySession();
}
}); });
Signals.addSignalMethods(AuthenticationDialog.prototype);
var AuthenticationAgent = class { var AuthenticationAgent = new Lang.Class({
constructor() { Name: 'AuthenticationAgent',
_init() {
this._currentDialog = null; this._currentDialog = null;
this._handle = null; this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent(); this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', this._onInitiate.bind(this)); this._native.connect('initiate', this._onInitiate.bind(this));
this._native.connect('cancel', this._onCancel.bind(this)); this._native.connect('cancel', this._onCancel.bind(this));
this._sessionUpdatedId = 0; this._sessionUpdatedId = 0;
} },
enable() { enable() {
try { try {
this._native.register(); this._native.register();
} catch (e) { } catch(e) {
log('Failed to register AuthenticationAgent'); log('Failed to register AuthenticationAgent');
} }
} },
disable() { disable() {
try { try {
this._native.unregister(); this._native.unregister();
} catch (e) { } catch(e) {
log('Failed to unregister AuthenticationAgent'); log('Failed to unregister AuthenticationAgent');
} }
} },
_onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames) { _onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames) {
// Don't pop up a dialog while locked // Don't pop up a dialog while locked
@@ -381,18 +406,19 @@ var AuthenticationAgent = class {
this._currentDialog.connect('done', this._onDialogDone.bind(this)); this._currentDialog.connect('done', this._onDialogDone.bind(this));
this._currentDialog.performAuthentication(); this._currentDialog.performAuthentication();
} },
_onCancel(nativeAgent) { _onCancel(nativeAgent) {
this._completeRequest(false); this._completeRequest(false);
} },
_onDialogDone(dialog, dismissed) { _onDialogDone(dialog, dismissed) {
this._completeRequest(dismissed); this._completeRequest(dismissed);
} },
_completeRequest(dismissed) { _completeRequest(dismissed) {
this._currentDialog.close(); this._currentDialog.close();
this._currentDialog.destroySession();
this._currentDialog = null; this._currentDialog = null;
if (this._sessionUpdatedId) if (this._sessionUpdatedId)
@@ -400,7 +426,7 @@ var AuthenticationAgent = class {
this._sessionUpdatedId = 0; this._sessionUpdatedId = 0;
this._native.complete(dismissed); this._native.complete(dismissed);
} },
}; });
var Component = AuthenticationAgent; var Component = AuthenticationAgent;

View File

@@ -1,14 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, GObject, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Signals = imports.signals;
const St = imports.gi.St;
var Tpl = null; var Tpl = null;
var Tp = null; var Tp = null;
try { try {
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi); Tpl = imports.gi.TelepathyLogger;
} catch (e) { Tp = imports.gi.TelepathyGLib;
} catch(e) {
log('Telepathy is not available, chat integration will be disabled.'); log('Telepathy is not available, chat integration will be disabled.');
} }
@@ -17,6 +23,7 @@ const Main = imports.ui.main;
const MessageList = imports.ui.messageList; const MessageList = imports.ui.messageList;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params; const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util; const Util = imports.misc.util;
const HAVE_TP = (Tp != null && Tpl != null); const HAVE_TP = (Tp != null && Tpl != null);
@@ -40,6 +47,8 @@ var NotificationDirection = {
RECEIVED: 'chat-received' RECEIVED: 'chat-received'
}; };
var N_ = s => s;
function makeMessageFromTpMessage(tpMessage, direction) { function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text(); let [text, flags] = tpMessage.to_text();
@@ -70,15 +79,17 @@ function makeMessageFromTplEvent(event) {
}; };
} }
var TelepathyComponent = class { var TelepathyComponent = new Lang.Class({
constructor() { Name: 'TelepathyComponent',
_init() {
this._client = null; this._client = null;
if (!HAVE_TP) if (!HAVE_TP)
return; // Telepathy isn't available return; // Telepathy isn't available
this._client = new TelepathyClient(); this._client = new TelepathyClient();
} },
enable() { enable() {
if (!this._client) if (!this._client)
@@ -87,12 +98,12 @@ var TelepathyComponent = class {
try { try {
this._client.register(); this._client.register();
} catch (e) { } catch (e) {
throw new Error(`Could not register Telepathy client. Error: ${e}`); throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
} }
if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core())) if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
this._client.account_manager.prepare_async(null, null); this._client.account_manager.prepare_async(null, null);
} },
disable() { disable() {
if (!this._client) if (!this._client)
@@ -100,10 +111,12 @@ var TelepathyComponent = class {
this._client.unregister(); this._client.unregister();
} }
}; });
var TelepathyClient = HAVE_TP ? new Lang.Class({
Name: 'TelepathyClient',
Extends: Tp.BaseClient,
var TelepathyClient = HAVE_TP ? GObject.registerClass(
class TelepathyClient extends Tp.BaseClient {
_init() { _init() {
// channel path -> ChatSource // channel path -> ChatSource
this._chatSources = {}; this._chatSources = {};
@@ -127,7 +140,7 @@ class TelepathyClient extends Tp.BaseClient {
// channel matching its filters is detected. // channel matching its filters is detected.
// The second argument, recover, means _observeChannels will be run // The second argument, recover, means _observeChannels will be run
// for any existing channel as well. // for any existing channel as well.
super._init({ name: 'GnomeShell', this.parent({ name: 'GnomeShell',
account_manager: this._accountManager, account_manager: this._accountManager,
uniquify_name: true }); uniquify_name: true });
@@ -145,10 +158,10 @@ class TelepathyClient extends Tp.BaseClient {
// needed // needed
this.set_delegated_channels_callback( this.set_delegated_channels_callback(
this._delegatedChannelsCb.bind(this)); this._delegatedChannelsCb.bind(this));
} },
vfunc_observe_channels(...args) { vfunc_observe_channels(account, conn, channels,
let [account, conn, channels, dispatchOp, requests, context] = args; dispatchOp, requests, context) {
let len = channels.length; let len = channels.length;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
let channel = channels[i]; let channel = channels[i];
@@ -166,7 +179,7 @@ class TelepathyClient extends Tp.BaseClient {
} }
context.accept(); context.accept();
} },
_createChatSource(account, conn, channel, contact) { _createChatSource(account, conn, channel, contact) {
if (this._chatSources[channel.get_object_path()]) if (this._chatSources[channel.get_object_path()])
@@ -178,13 +191,13 @@ class TelepathyClient extends Tp.BaseClient {
source.connect('destroy', () => { source.connect('destroy', () => {
delete this._chatSources[channel.get_object_path()]; delete this._chatSources[channel.get_object_path()];
}); });
} },
vfunc_handle_channels(...args) { vfunc_handle_channels(account, conn, channels, requests,
let [account, conn, channels, requests, userActionTime, context] = args; user_action_time, context) {
this._handlingChannels(account, conn, channels, true); this._handlingChannels(account, conn, channels, true);
context.accept(); context.accept();
} },
_handlingChannels(account, conn, channels, notify) { _handlingChannels(account, conn, channels, notify) {
let len = channels.length; let len = channels.length;
@@ -218,10 +231,10 @@ class TelepathyClient extends Tp.BaseClient {
source.notify(); source.notify();
} }
} }
} },
vfunc_add_dispatch_operation(...args) { vfunc_add_dispatch_operation(account, conn, channels,
let [account, conn, channels, dispatchOp, context] = args; dispatchOp, context) {
let channel = channels[0]; let channel = channels[0];
let chanType = channel.get_channel_type(); let chanType = channel.get_channel_type();
@@ -236,7 +249,7 @@ class TelepathyClient extends Tp.BaseClient {
else else
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT, context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
message: 'Unsupported channel type' })); message: 'Unsupported channel type' }));
} },
_approveTextChannel(account, conn, channel, dispatchOp, context) { _approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle(); let [targetHandle, targetHandleType] = channel.get_handle();
@@ -253,27 +266,30 @@ class TelepathyClient extends Tp.BaseClient {
dispatchOp.claim_with_finish(result); dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false); this._handlingChannels(account, conn, [channel], false);
} catch (err) { } catch (err) {
log(`Failed to Claim channel: ${err}`); log('Failed to Claim channel: ' + err);
} }
}); });
context.accept(); context.accept();
} },
_delegatedChannelsCb(client, channels) { _delegatedChannelsCb(client, channels) {
// Nothing to do as we don't make a distinction between observed and // Nothing to do as we don't make a distinction between observed and
// handled channels. // handled channels.
} },
}) : null; }) : null;
var ChatSource = class extends MessageTray.Source { var ChatSource = new Lang.Class({
constructor(account, conn, channel, contact, client) { Name: 'ChatSource',
super(contact.get_alias()); Extends: MessageTray.Source,
_init(account, conn, channel, contact, client) {
this._account = account; this._account = account;
this._contact = contact; this._contact = contact;
this._client = client; this._client = client;
this.parent(contact.get_alias());
this.isChat = true; this.isChat = true;
this._pendingMessages = []; this._pendingMessages = [];
@@ -297,7 +313,7 @@ var ChatSource = class extends MessageTray.Source {
Main.messageTray.add(this); Main.messageTray.add(this);
this._getLogMessages(); this._getLogMessages();
} },
_ensureNotification() { _ensureNotification() {
if (this._notification) if (this._notification)
@@ -313,13 +329,13 @@ var ChatSource = class extends MessageTray.Source {
this._notification = null; this._notification = null;
}); });
this.pushNotification(this._notification); this.pushNotification(this._notification);
} },
_createPolicy() { _createPolicy() {
if (this._account.protocol_name == 'irc') if (this._account.protocol_name == 'irc')
return new MessageTray.NotificationApplicationPolicy('org.gnome.Polari'); return new MessageTray.NotificationApplicationPolicy('org.gnome.Polari');
return new MessageTray.NotificationApplicationPolicy('empathy'); return new MessageTray.NotificationApplicationPolicy('empathy');
} },
createBanner() { createBanner() {
this._banner = new ChatNotificationBanner(this._notification); this._banner = new ChatNotificationBanner(this._notification);
@@ -332,7 +348,7 @@ var ChatSource = class extends MessageTray.Source {
}); });
return this._banner; return this._banner;
} },
_updateAlias() { _updateAlias() {
let oldAlias = this.title; let oldAlias = this.title;
@@ -344,7 +360,7 @@ var ChatSource = class extends MessageTray.Source {
this.setTitle(newAlias); this.setTitle(newAlias);
if (this._notification) if (this._notification)
this._notification.appendAliasChange(oldAlias, newAlias); this._notification.appendAliasChange(oldAlias, newAlias);
} },
getIcon() { getIcon() {
let file = this._contact.get_avatar_file(); let file = this._contact.get_avatar_file();
@@ -353,7 +369,7 @@ var ChatSource = class extends MessageTray.Source {
} else { } else {
return new Gio.ThemedIcon({ name: 'avatar-default' }); return new Gio.ThemedIcon({ name: 'avatar-default' });
} }
} },
getSecondaryIcon() { getSecondaryIcon() {
let iconName; let iconName;
@@ -382,7 +398,7 @@ var ChatSource = class extends MessageTray.Source {
iconName = 'user-offline'; iconName = 'user-offline';
} }
return new Gio.ThemedIcon({ name: iconName }); return new Gio.ThemedIcon({ name: iconName });
} },
_updateAvatarIcon() { _updateAvatarIcon() {
this.iconUpdated(); this.iconUpdated();
@@ -390,7 +406,7 @@ var ChatSource = class extends MessageTray.Source {
this._notification.update(this._notification.title, this._notification.update(this._notification.title,
this._notification.bannerBodyText, this._notification.bannerBodyText,
{ gicon: this.getIcon() }); { gicon: this.getIcon() });
} },
open() { open() {
Main.overview.hide(); Main.overview.hide();
@@ -399,7 +415,7 @@ var ChatSource = class extends MessageTray.Source {
if (this._client.is_handling_channel(this._channel)) { if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy or Polari // We are handling the channel, try to pass it to Empathy or Polari
// (depending on the channel type) // (depending on the channel type)
// We don't check if either app is available - mission control will // We don't check if either app is availble - mission control will
// fallback to something else if activation fails // fallback to something else if activation fails
let target; let target;
@@ -415,7 +431,7 @@ var ChatSource = class extends MessageTray.Source {
cd.present_channel_async(this._channel, global.get_current_time(), null); cd.present_channel_async(this._channel, global.get_current_time(), null);
} }
} },
_getLogMessages() { _getLogMessages() {
let logManager = Tpl.LogManager.dup_singleton(); let logManager = Tpl.LogManager.dup_singleton();
@@ -424,7 +440,7 @@ var ChatSource = class extends MessageTray.Source {
logManager.get_filtered_events_async(this._account, entity, logManager.get_filtered_events_async(this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES, Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, this._displayPendingMessages.bind(this)); null, this._displayPendingMessages.bind(this));
} },
_displayPendingMessages(logManager, result) { _displayPendingMessages(logManager, result) {
let [success, events] = logManager.get_filtered_events_finish(result); let [success, events] = logManager.get_filtered_events_finish(result);
@@ -477,7 +493,7 @@ var ChatSource = class extends MessageTray.Source {
if (pendingMessages.length > 0) if (pendingMessages.length > 0)
this.notify(); this.notify();
} },
destroy(reason) { destroy(reason) {
if (this._client.is_handling_channel(this._channel)) { if (this._client.is_handling_channel(this._channel)) {
@@ -511,25 +527,25 @@ var ChatSource = class extends MessageTray.Source {
this._contact.disconnect(this._notifyAvatarId); this._contact.disconnect(this._notifyAvatarId);
this._contact.disconnect(this._presenceChangedId); this._contact.disconnect(this._presenceChangedId);
super.destroy(reason); this.parent(reason);
} },
_channelClosed() { _channelClosed() {
this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED); this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
} },
/* All messages are new messages for Telepathy sources */ /* All messages are new messages for Telepathy sources */
get count() { get count() {
return this._pendingMessages.length; return this._pendingMessages.length;
} },
get unseenCount() { get unseenCount() {
return this.count; return this.count;
} },
get countVisible() { get countVisible() {
return this.count > 0; return this.count > 0;
} },
_messageReceived(channel, message) { _messageReceived(channel, message) {
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT) if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
@@ -549,7 +565,7 @@ var ChatSource = class extends MessageTray.Source {
this._notifyTimeoutId = Mainloop.timeout_add(500, this._notifyTimeoutId = Mainloop.timeout_add(500,
this._notifyTimeout.bind(this)); this._notifyTimeout.bind(this));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout'); GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
} },
_notifyTimeout() { _notifyTimeout() {
if (this._pendingMessages.length != 0) if (this._pendingMessages.length != 0)
@@ -558,7 +574,7 @@ var ChatSource = class extends MessageTray.Source {
this._notifyTimeoutId = 0; this._notifyTimeoutId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} },
// This is called for both messages we send from // This is called for both messages we send from
// our client and other clients as well. // our client and other clients as well.
@@ -566,11 +582,11 @@ var ChatSource = class extends MessageTray.Source {
this._ensureNotification(); this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT); message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message); this._notification.appendMessage(message);
} },
notify() { notify() {
super.notify(this._notification); this.parent(this._notification);
} },
respond(text) { respond(text) {
let type; let type;
@@ -585,7 +601,7 @@ var ChatSource = class extends MessageTray.Source {
this._channel.send_message_async(msg, 0, (src, result) => { this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result); this._channel.send_message_finish(result);
}); });
} },
setChatState(state) { setChatState(state) {
// We don't want to send COMPOSING every time a letter is typed into // We don't want to send COMPOSING every time a letter is typed into
@@ -598,14 +614,14 @@ var ChatSource = class extends MessageTray.Source {
this._chatState = state; this._chatState = state;
this._channel.set_chat_state_async(state, null); this._channel.set_chat_state_async(state, null);
} }
} },
_presenceChanged(contact, presence, status, message) { _presenceChanged(contact, presence, status, message) {
if (this._notification) if (this._notification)
this._notification.update(this._notification.title, this._notification.update(this._notification.title,
this._notification.bannerBodyText, this._notification.bannerBodyText,
{ secondaryGIcon: this.getSecondaryIcon() }); { secondaryGIcon: this.getSecondaryIcon() });
} },
_pendingRemoved(channel, message) { _pendingRemoved(channel, message) {
let idx = this._pendingMessages.indexOf(message); let idx = this._pendingMessages.indexOf(message);
@@ -618,32 +634,35 @@ var ChatSource = class extends MessageTray.Source {
if (this._pendingMessages.length == 0 && if (this._pendingMessages.length == 0 &&
this._banner && !this._banner.expanded) this._banner && !this._banner.expanded)
this._banner.hide(); this._banner.hide();
} },
_ackMessages() { _ackMessages() {
// Don't clear our messages here, tp-glib will send a // Don't clear our messages here, tp-glib will send a
// 'pending-message-removed' for each one. // 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null); this._channel.ack_all_pending_messages_async(null);
} }
}; });
var ChatNotification = class extends MessageTray.Notification { var ChatNotification = new Lang.Class({
constructor(source) { Name: 'ChatNotification',
super(source, source.title, null, Extends: MessageTray.Notification,
_init(source) {
this.parent(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() }); { secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH); this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true); this.setResident(true);
this.messages = []; this.messages = [];
this._timestampTimeoutId = 0; this._timestampTimeoutId = 0;
} },
destroy(reason) { destroy(reason) {
if (this._timestampTimeoutId) if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId); Mainloop.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0; this._timestampTimeoutId = 0;
super.destroy(reason); this.parent(reason);
} },
/** /**
* appendMessage: * appendMessage:
@@ -681,7 +700,7 @@ var ChatNotification = class extends MessageTray.Notification {
styles: styles, styles: styles,
timestamp: message.timestamp, timestamp: message.timestamp,
noTimestamp: noTimestamp }); noTimestamp: noTimestamp });
} },
_filterMessages() { _filterMessages() {
if (this.messages.length < 1) if (this.messages.length < 1)
@@ -706,7 +725,7 @@ var ChatNotification = class extends MessageTray.Notification {
for (let i = 0; i < expired.length; i++) for (let i = 0; i < expired.length; i++)
this.emit('message-removed', expired[i]); this.emit('message-removed', expired[i]);
} }
} },
/** /**
* _append: * _append:
@@ -754,7 +773,7 @@ var ChatNotification = class extends MessageTray.Notification {
} }
this._filterMessages(); this._filterMessages();
} },
appendTimestamp() { appendTimestamp() {
this._timestampTimeoutId = 0; this._timestampTimeoutId = 0;
@@ -765,7 +784,7 @@ var ChatNotification = class extends MessageTray.Notification {
this._filterMessages(); this._filterMessages();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} },
appendAliasChange(oldAlias, newAlias) { appendAliasChange(oldAlias, newAlias) {
oldAlias = GLib.markup_escape_text(oldAlias, -1); oldAlias = GLib.markup_escape_text(oldAlias, -1);
@@ -781,19 +800,24 @@ var ChatNotification = class extends MessageTray.Notification {
this._filterMessages(); this._filterMessages();
} }
}; });
var ChatLineBox = new Lang.Class({
Name: 'ChatLineBox',
Extends: St.BoxLayout,
var ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout {
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(forWidth) {
let [, natHeight] = super.vfunc_get_preferred_height(forWidth); let [, natHeight] = this.parent(forWidth);
return [natHeight, natHeight]; return [natHeight, natHeight];
} }
}); });
var ChatNotificationBanner = class extends MessageTray.NotificationBanner { var ChatNotificationBanner = new Lang.Class({
constructor(notification) { Name: 'ChatNotificationBanner',
super(notification); Extends: MessageTray.NotificationBanner,
_init(notification) {
this.parent(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response', this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true, x_expand: true,
@@ -811,8 +835,8 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
}); });
this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade', this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade',
vscrollbar_policy: St.PolicyType.AUTOMATIC, vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: St.PolicyType.NEVER, hscrollbar_policy: Gtk.PolicyType.NEVER,
visible: this.expanded }); visible: this.expanded });
this._contentArea = new St.BoxLayout({ style_class: 'chat-body', this._contentArea = new St.BoxLayout({ style_class: 'chat-body',
vertical: true }); vertical: true });
@@ -856,14 +880,14 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
for (let i = this.notification.messages.length - 1; i >= 0; i--) for (let i = this.notification.messages.length - 1; i >= 0; i--)
this._addMessage(this.notification.messages[i]); this._addMessage(this.notification.messages[i]);
} },
_onDestroy() { _onDestroy() {
super._onDestroy(); this.parent();
this.notification.disconnect(this._messageAddedId); this.notification.disconnect(this._messageAddedId);
this.notification.disconnect(this._messageRemovedId); this.notification.disconnect(this._messageRemovedId);
this.notification.disconnect(this._timestampChangedId); this.notification.disconnect(this._timestampChangedId);
} },
scrollTo(side) { scrollTo(side) {
let adjustment = this._scrollArea.vscroll.adjustment; let adjustment = this._scrollArea.vscroll.adjustment;
@@ -871,11 +895,11 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
adjustment.value = adjustment.lower; adjustment.value = adjustment.lower;
else if (side == St.Side.BOTTOM) else if (side == St.Side.BOTTOM)
adjustment.value = adjustment.upper; adjustment.value = adjustment.upper;
} },
hide() { hide() {
this.emit('done-displaying'); this.emit('done-displaying');
} },
_addMessage(message) { _addMessage(message) {
let highlighter = new MessageList.URLHighlighter(message.body, true, true); let highlighter = new MessageList.URLHighlighter(message.body, true, true);
@@ -897,7 +921,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
this._messageActors.set(message, lineBox); this._messageActors.set(message, lineBox);
this._updateTimestamp(message); this._updateTimestamp(message);
} },
_updateTimestamp(message) { _updateTimestamp(message) {
let actor = this._messageActors.get(message); let actor = this._messageActors.get(message);
@@ -918,7 +942,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
actor.add_actor(timeLabel); actor.add_actor(timeLabel);
} }
} },
_onEntryActivated() { _onEntryActivated() {
let text = this._responseEntry.get_text(); let text = this._responseEntry.get_text();
@@ -931,7 +955,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
// see Source._messageSent // see Source._messageSent
this._responseEntry.set_text(''); this._responseEntry.set_text('');
this.notification.source.respond(text); this.notification.source.respond(text);
} },
_composingStopTimeout() { _composingStopTimeout() {
this._composingTimeoutId = 0; this._composingTimeoutId = 0;
@@ -939,7 +963,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
this.notification.source.setChatState(Tp.ChannelChatState.PAUSED); this.notification.source.setChatState(Tp.ChannelChatState.PAUSED);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
} },
_onEntryChanged() { _onEntryChanged() {
let text = this._responseEntry.get_text(); let text = this._responseEntry.get_text();
@@ -966,6 +990,6 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE); this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
} }
} }
}; });
var Component = TelepathyComponent; var Component = TelepathyComponent;

View File

@@ -1,12 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GObject, Meta, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
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 SwitcherPopup = imports.ui.switcherPopup; const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params; const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var POPUP_APPICON_SIZE = 96; var POPUP_APPICON_SIZE = 96;
var POPUP_FADE_TIME = 0.1; // seconds
var SortGroup = { var SortGroup = {
TOP: 0, TOP: 0,
@@ -14,13 +21,15 @@ var SortGroup = {
BOTTOM: 2 BOTTOM: 2
}; };
var CtrlAltTabManager = class CtrlAltTabManager { var CtrlAltTabManager = new Lang.Class({
constructor() { Name: 'CtrlAltTabManager',
_init() {
this._items = []; this._items = [];
this.addGroup(global.window_group, _("Windows"), this.addGroup(global.window_group, _("Windows"),
'focus-windows-symbolic', { sortGroup: SortGroup.TOP, 'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: this._focusWindows.bind(this) }); focusCallback: this._focusWindows.bind(this) });
} },
addGroup(root, name, icon, params) { addGroup(root, name, icon, params) {
let item = Params.parse(params, { sortGroup: SortGroup.MIDDLE, let item = Params.parse(params, { sortGroup: SortGroup.MIDDLE,
@@ -32,10 +41,10 @@ var CtrlAltTabManager = class CtrlAltTabManager {
item.iconName = icon; item.iconName = icon;
this._items.push(item); this._items.push(item);
root.connect('destroy', () => this.removeGroup(root)); root.connect('destroy', () => { this.removeGroup(root); });
if (root instanceof St.Widget) if (root instanceof St.Widget)
global.focus_manager.add_group(root); global.focus_manager.add_group(root);
} },
removeGroup(root) { removeGroup(root) {
if (root instanceof St.Widget) if (root instanceof St.Widget)
@@ -46,14 +55,14 @@ var CtrlAltTabManager = class CtrlAltTabManager {
return; return;
} }
} }
} },
focusGroup(item, timestamp) { focusGroup(item, timestamp) {
if (item.focusCallback) if (item.focusCallback)
item.focusCallback(timestamp); item.focusCallback(timestamp);
else else
item.root.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); item.root.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
} },
// Sort the items into a consistent order; panel first, tray last, // Sort the items into a consistent order; panel first, tray last,
// and everything else in between, sorted by X coordinate, so that // and everything else in between, sorted by X coordinate, so that
@@ -68,7 +77,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
[bx, y] = b.proxy.get_transformed_position(); [bx, y] = b.proxy.get_transformed_position();
return ax - bx; return ax - bx;
} },
popup(backward, binding, mask) { popup(backward, binding, mask) {
// Start with the set of focus groups that are currently mapped // Start with the set of focus groups that are currently mapped
@@ -93,9 +102,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
if (app) if (app)
icon = app.create_icon_texture(POPUP_APPICON_SIZE); icon = app.create_icon_texture(POPUP_APPICON_SIZE);
else else
icon = textureCache.bind_cairo_surface_property(windows[i], icon = textureCache.bind_cairo_surface_property(windows[i], 'icon');
'icon',
POPUP_APPICON_SIZE);
} }
items.push({ name: windows[i].title, items.push({ name: windows[i].title,
@@ -123,20 +130,22 @@ var CtrlAltTabManager = class CtrlAltTabManager {
this._popup = null; this._popup = null;
}); });
} }
} },
_focusWindows(timestamp) { _focusWindows(timestamp) {
global.display.focus_default_window(timestamp); global.display.focus_default_window(timestamp);
} }
}; });
var CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup,
var CtrlAltTabPopup = GObject.registerClass(
class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
_init(items) { _init(items) {
super._init(items); this.parent(items);
this._switcherList = new CtrlAltTabSwitcher(this._items); this._switcherList = new CtrlAltTabSwitcher(this._items);
} },
_keyPressHandler(keysym, action) { _keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS) if (action == Meta.KeyBindingAction.SWITCH_PANELS)
@@ -151,22 +160,24 @@ class CtrlAltTabPopup extends SwitcherPopup.SwitcherPopup {
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} },
_finish(time) { _finish(time) {
super._finish(time); this.parent(time);
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time); Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
} },
}); });
var CtrlAltTabSwitcher = GObject.registerClass( var CtrlAltTabSwitcher = new Lang.Class({
class CtrlAltTabSwitcher extends SwitcherPopup.SwitcherList { Name: 'CtrlAltTabSwitcher',
Extends: SwitcherPopup.SwitcherList,
_init(items) { _init(items) {
super._init(true); this.parent(true);
for (let i = 0; i < items.length; i++) for (let i = 0; i < items.length; i++)
this._addIcon(items[i]); this._addIcon(items[i]);
} },
_addIcon(item) { _addIcon(item) {
let box = new St.BoxLayout({ style_class: 'alt-tab-app', let box = new St.BoxLayout({ style_class: 'alt-tab-app',

View File

@@ -1,8 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Mainloop = imports.mainloop; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Signals = imports.signals; const Signals = imports.signals;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites; const AppFavorites = imports.ui.appFavorites;
@@ -10,6 +16,7 @@ const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
var DASH_ANIMATION_TIME = 0.2; var DASH_ANIMATION_TIME = 0.2;
var DASH_ITEM_LABEL_SHOW_TIME = 0.15; var DASH_ITEM_LABEL_SHOW_TIME = 0.15;
@@ -26,16 +33,18 @@ function getAppFromSource(source) {
// A container like StBin, but taking the child's scale into account // A container like StBin, but taking the child's scale into account
// when requesting a size // when requesting a size
var DashItemContainer = GObject.registerClass( var DashItemContainer = new Lang.Class({
class DashItemContainer extends St.Widget { Name: 'DashItemContainer',
Extends: St.Widget,
_init() { _init() {
super._init({ style_class: 'dash-item-container', this.parent({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }), pivot_point: new Clutter.Point({ x: .5, y: .5 }),
x_expand: true, x_expand: true,
x_align: Clutter.ActorAlign.CENTER }); x_align: Clutter.ActorAlign.CENTER });
this._labelText = ""; this._labelText = "";
this.label = new St.Label({ style_class: 'dash-label' }); this.label = new St.Label({ style_class: 'dash-label'});
this.label.hide(); this.label.hide();
Main.layoutManager.addChrome(this.label); Main.layoutManager.addChrome(this.label);
this.label_actor = this.label; this.label_actor = this.label;
@@ -50,23 +59,23 @@ class DashItemContainer extends St.Widget {
this.child.destroy(); this.child.destroy();
this.label.destroy(); this.label.destroy();
}); });
} },
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
forWidth = themeNode.adjust_for_width(forWidth); forWidth = themeNode.adjust_for_width(forWidth);
let [minHeight, natHeight] = super.vfunc_get_preferred_height(forWidth); let [minHeight, natHeight] = this.parent(forWidth);
return themeNode.adjust_preferred_height(minHeight * this.scale_y, return themeNode.adjust_preferred_height(minHeight * this.scale_y,
natHeight * this.scale_y); natHeight * this.scale_y);
} },
vfunc_get_preferred_width(forHeight) { vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
forHeight = themeNode.adjust_for_height(forHeight); forHeight = themeNode.adjust_for_height(forHeight);
let [minWidth, natWidth] = super.vfunc_get_preferred_width(forHeight); let [minWidth, natWidth] = this.parent(forHeight);
return themeNode.adjust_preferred_width(minWidth * this.scale_x, return themeNode.adjust_preferred_width(minWidth * this.scale_x,
natWidth * this.scale_x); natWidth * this.scale_x);
} },
showLabel() { showLabel() {
if (!this._labelText) if (!this._labelText)
@@ -81,7 +90,7 @@ class DashItemContainer extends St.Widget {
let itemHeight = this.allocation.y2 - this.allocation.y1; let itemHeight = this.allocation.y2 - this.allocation.y1;
let labelHeight = this.label.get_height(); let labelHeight = this.label.get_height();
let yOffset = Math.floor((itemHeight - labelHeight) / 2); let yOffset = Math.floor((itemHeight - labelHeight) / 2)
let y = stageY + yOffset; let y = stageY + yOffset;
@@ -100,12 +109,12 @@ class DashItemContainer extends St.Widget {
time: DASH_ITEM_LABEL_SHOW_TIME, time: DASH_ITEM_LABEL_SHOW_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
}); });
} },
setLabelText(text) { setLabelText(text) {
this._labelText = text; this._labelText = text;
this.child.accessible_name = text; this.child.accessible_name = text;
} },
hideLabel() { hideLabel() {
Tweener.addTween(this.label, Tweener.addTween(this.label,
@@ -116,7 +125,7 @@ class DashItemContainer extends St.Widget {
this.label.hide(); this.label.hide();
} }
}); });
} },
setChild(actor) { setChild(actor) {
if (this.child == actor) if (this.child == actor)
@@ -129,7 +138,7 @@ class DashItemContainer extends St.Widget {
this.set_scale(this._childScale, this._childScale); this.set_scale(this._childScale, this._childScale);
this.set_opacity(this._childOpacity); this.set_opacity(this._childOpacity);
} },
show(animate) { show(animate) {
if (this.child == null) if (this.child == null)
@@ -142,7 +151,7 @@ class DashItemContainer extends St.Widget {
time: time, time: time,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
} },
animateOutAndDestroy() { animateOutAndDestroy() {
this.label.hide(); this.label.hide();
@@ -162,35 +171,37 @@ class DashItemContainer extends St.Widget {
this.destroy(); this.destroy();
} }
}); });
} },
set childScale(scale) { set childScale(scale) {
this._childScale = scale; this._childScale = scale;
this.set_scale(scale, scale); this.set_scale(scale, scale);
this.queue_relayout(); this.queue_relayout();
} },
get childScale() { get childScale() {
return this._childScale; return this._childScale;
} },
set childOpacity(opacity) { set childOpacity(opacity) {
this._childOpacity = opacity; this._childOpacity = opacity;
this.set_opacity(opacity); this.set_opacity(opacity);
this.queue_redraw(); this.queue_redraw();
} },
get childOpacity() { get childOpacity() {
return this._childOpacity; return this._childOpacity;
} }
}); });
var ShowAppsIcon = GObject.registerClass( var ShowAppsIcon = new Lang.Class({
class ShowAppsIcon extends DashItemContainer { Name: 'ShowAppsIcon',
Extends: DashItemContainer,
_init() { _init() {
super._init(); this.parent();
this.toggleButton = new St.Button({ style_class: 'show-apps', this.toggleButton = new St.Button({ style_class: 'show-apps',
track_hover: true, track_hover: true,
@@ -206,7 +217,7 @@ class ShowAppsIcon extends DashItemContainer {
this.setChild(this.toggleButton); this.setChild(this.toggleButton);
this.setDragApp(null); this.setDragApp(null);
} },
_createIcon(size) { _createIcon(size) {
this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic', this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic',
@@ -214,7 +225,7 @@ class ShowAppsIcon extends DashItemContainer {
style_class: 'show-apps-icon', style_class: 'show-apps-icon',
track_hover: true }); track_hover: true });
return this._iconActor; return this._iconActor;
} },
_canRemoveApp(app) { _canRemoveApp(app) {
if (app == null) if (app == null)
@@ -226,7 +237,7 @@ class ShowAppsIcon extends DashItemContainer {
let id = app.get_id(); let id = app.get_id();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(id); let isFavorite = AppFavorites.getAppFavorites().isFavorite(id);
return isFavorite; return isFavorite;
} },
setDragApp(app) { setDragApp(app) {
let canRemove = this._canRemoveApp(app); let canRemove = this._canRemoveApp(app);
@@ -239,14 +250,14 @@ class ShowAppsIcon extends DashItemContainer {
this.setLabelText(_("Remove from Favorites")); this.setLabelText(_("Remove from Favorites"));
else else
this.setLabelText(_("Show Applications")); this.setLabelText(_("Show Applications"));
} },
handleDragOver(source, actor, x, y, time) { handleDragOver(source, actor, x, y, time) {
if (!this._canRemoveApp(getAppFromSource(source))) if (!this._canRemoveApp(getAppFromSource(source)))
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
} },
acceptDrop(source, actor, x, y, time) { acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source); let app = getAppFromSource(source);
@@ -264,30 +275,36 @@ class ShowAppsIcon extends DashItemContainer {
} }
}); });
var DragPlaceholderItem = GObject.registerClass( var DragPlaceholderItem = new Lang.Class({
class DragPlaceholderItem extends DashItemContainer { Name: 'DragPlaceholderItem',
Extends: DashItemContainer,
_init() { _init() {
super._init(); this.parent();
this.setChild(new St.Bin({ style_class: 'placeholder' })); this.setChild(new St.Bin({ style_class: 'placeholder' }));
} }
}); });
var EmptyDropTargetItem = GObject.registerClass( var EmptyDropTargetItem = new Lang.Class({
class EmptyDropTargetItem extends DashItemContainer { Name: 'EmptyDropTargetItem',
Extends: DashItemContainer,
_init() { _init() {
super._init(); this.parent();
this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' })); this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
} }
}); });
var DashActor = GObject.registerClass( var DashActor = new Lang.Class({
class DashActor extends St.Widget { Name: 'DashActor',
Extends: St.Widget,
_init() { _init() {
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL }); let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
super._init({ name: 'dash', this.parent({ name: 'dash',
layout_manager: layout, layout_manager: layout,
clip_to_allocation: true }); clip_to_allocation: true });
} },
vfunc_allocate(box, flags) { vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box); let contentBox = this.get_theme_node().get_content_box(box);
@@ -308,7 +325,7 @@ class DashActor extends St.Widget {
childBox.y1 = contentBox.y2 - showAppsNatHeight; childBox.y1 = contentBox.y2 - showAppsNatHeight;
childBox.y2 = contentBox.y2; childBox.y2 = contentBox.y2;
showAppsButton.allocate(childBox, flags); showAppsButton.allocate(childBox, flags);
} },
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(forWidth) {
// We want to request the natural height of all our children // We want to request the natural height of all our children
@@ -316,22 +333,24 @@ class DashActor extends St.Widget {
// then calls BoxLayout), but we only request the showApps // then calls BoxLayout), but we only request the showApps
// button as the minimum size // button as the minimum size
let [, natHeight] = super.vfunc_get_preferred_height(forWidth); let [, natHeight] = this.parent(forWidth);
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let adjustedForWidth = themeNode.adjust_for_width(forWidth); let adjustedForWidth = themeNode.adjust_for_width(forWidth);
let [, showAppsButton] = this.get_children(); let [, showAppsButton] = this.get_children();
let [minHeight] = showAppsButton.get_preferred_height(adjustedForWidth); let [minHeight, ] = showAppsButton.get_preferred_height(adjustedForWidth);
[minHeight] = themeNode.adjust_preferred_height(minHeight, natHeight); [minHeight, ] = themeNode.adjust_preferred_height(minHeight, natHeight);
return [minHeight, natHeight]; return [minHeight, natHeight];
} }
}); });
const baseIconSizes = [16, 22, 24, 32, 48, 64]; const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
var Dash = class Dash { var Dash = new Lang.Class({
constructor() { Name: 'Dash',
_init() {
this._maxHeight = -1; this._maxHeight = -1;
this.iconSize = 64; this.iconSize = 64;
this._shownInitially = false; this._shownInitially = false;
@@ -388,7 +407,7 @@ var Dash = class Dash {
// Translators: this is the name of the dock/favorites area on // Translators: this is the name of the dock/favorites area on
// the left of the overview // the left of the overview
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic'); Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
} },
_onDragBegin() { _onDragBegin() {
this._dragCancelled = false; this._dragCancelled = false;
@@ -402,26 +421,26 @@ var Dash = class Dash {
this._box.insert_child_at_index(this._emptyDropTarget, 0); this._box.insert_child_at_index(this._emptyDropTarget, 0);
this._emptyDropTarget.show(true); this._emptyDropTarget.show(true);
} }
} },
_onDragCancelled() { _onDragCancelled() {
this._dragCancelled = true; this._dragCancelled = true;
this._endDrag(); this._endDrag();
} },
_onDragEnd() { _onDragEnd() {
if (this._dragCancelled) if (this._dragCancelled)
return; return;
this._endDrag(); this._endDrag();
} },
_endDrag() { _endDrag() {
this._clearDragPlaceholder(); this._clearDragPlaceholder();
this._clearEmptyDropTarget(); this._clearEmptyDropTarget();
this._showAppsIcon.setDragApp(null); this._showAppsIcon.setDragApp(null);
DND.removeDragMonitor(this._dragMonitor); DND.removeDragMonitor(this._dragMonitor);
} },
_onDragMotion(dragEvent) { _onDragMotion(dragEvent) {
let app = getAppFromSource(dragEvent.source); let app = getAppFromSource(dragEvent.source);
@@ -440,18 +459,18 @@ var Dash = class Dash {
this._showAppsIcon.setDragApp(null); this._showAppsIcon.setDragApp(null);
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
} },
_appIdListToHash(apps) { _appIdListToHash(apps) {
let ids = {}; let ids = {};
for (let i = 0; i < apps.length; i++) for (let i = 0; i < apps.length; i++)
ids[apps[i].get_id()] = apps[i]; ids[apps[i].get_id()] = apps[i];
return ids; return ids;
} },
_queueRedisplay() { _queueRedisplay() {
Main.queueDeferredWork(this._workId); Main.queueDeferredWork(this._workId);
} },
_hookUpLabel(item, appIcon) { _hookUpLabel(item, appIcon) {
item.child.connect('notify::hover', () => { item.child.connect('notify::hover', () => {
@@ -471,7 +490,7 @@ var Dash = class Dash {
this._syncLabel(item, appIcon); this._syncLabel(item, appIcon);
}); });
} }
} },
_createAppItem(app) { _createAppItem(app) {
let appIcon = new AppDisplay.AppIcon(app, let appIcon = new AppDisplay.AppIcon(app,
@@ -505,7 +524,7 @@ var Dash = class Dash {
this._hookUpLabel(item, appIcon); this._hookUpLabel(item, appIcon);
return item; return item;
} },
_itemMenuStateChanged(item, opened) { _itemMenuStateChanged(item, opened) {
// When the menu closes, it calls sync_hover, which means // When the menu closes, it calls sync_hover, which means
@@ -518,7 +537,7 @@ var Dash = class Dash {
item.hideLabel(); item.hideLabel();
} }
} },
_syncLabel(item, appIcon) { _syncLabel(item, appIcon) {
let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover(); let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover();
@@ -554,7 +573,7 @@ var Dash = class Dash {
GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing'); GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
} }
} }
} },
_adjustIconSize() { _adjustIconSize() {
// For the icon size, we only consider children which are "proper" // For the icon size, we only consider children which are "proper"
@@ -584,18 +603,22 @@ var Dash = class Dash {
let firstButton = iconChildren[0].child; let firstButton = iconChildren[0].child;
let firstIcon = firstButton._delegate.icon; let firstIcon = firstButton._delegate.icon;
// Enforce valid spacings during the size request let minHeight, natHeight;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
// Enforce the current icon size during the size request
firstIcon.icon.ensure_style(); firstIcon.icon.ensure_style();
let [, iconHeight] = firstIcon.icon.get_preferred_height(-1); let [, currentHeight] = firstIcon.icon.get_size();
let [, buttonHeight] = firstButton.get_preferred_height(-1); firstIcon.icon.set_height(this.iconSize * scaleFactor);
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
firstIcon.icon.set_height(currentHeight);
// Subtract icon padding and box spacing from the available height // Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (buttonHeight - iconHeight) + availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
(iconChildren.length - 1) * spacing; (iconChildren.length - 1) * spacing;
let availSize = availHeight / iconChildren.length; let availSize = availHeight / iconChildren.length;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let iconSizes = baseIconSizes.map(s => s * scaleFactor); let iconSizes = baseIconSizes.map(s => s * scaleFactor);
let newIconSize = baseIconSizes[0]; let newIconSize = baseIconSizes[0];
@@ -640,7 +663,7 @@ var Dash = class Dash {
transition: 'easeOutQuad', transition: 'easeOutQuad',
}); });
} }
} },
_redisplay() { _redisplay() {
let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
@@ -700,14 +723,14 @@ var Dash = class Dash {
} }
// App removed at oldIndex // App removed at oldIndex
if (oldApp && !newApps.includes(oldApp)) { if (oldApp && newApps.indexOf(oldApp) == -1) {
removedActors.push(children[oldIndex]); removedActors.push(children[oldIndex]);
oldIndex++; oldIndex++;
continue; continue;
} }
// App added at newIndex // App added at newIndex
if (newApp && !oldApps.includes(newApp)) { if (newApp && oldApps.indexOf(newApp) == -1) {
addedItems.push({ app: newApp, addedItems.push({ app: newApp,
item: this._createAppItem(newApp), item: this._createAppItem(newApp),
pos: newIndex }); pos: newIndex });
@@ -769,7 +792,7 @@ var Dash = class Dash {
// Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744 // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=692744
// Without it, StBoxLayout may use a stale size cache // Without it, StBoxLayout may use a stale size cache
this._box.queue_relayout(); this._box.queue_relayout();
} },
_clearDragPlaceholder() { _clearDragPlaceholder() {
if (this._dragPlaceholder) { if (this._dragPlaceholder) {
@@ -781,14 +804,14 @@ var Dash = class Dash {
this._dragPlaceholder = null; this._dragPlaceholder = null;
} }
this._dragPlaceholderPos = -1; this._dragPlaceholderPos = -1;
} },
_clearEmptyDropTarget() { _clearEmptyDropTarget() {
if (this._emptyDropTarget) { if (this._emptyDropTarget) {
this._emptyDropTarget.animateOutAndDestroy(); this._emptyDropTarget.animateOutAndDestroy();
this._emptyDropTarget = null; this._emptyDropTarget = null;
} }
} },
handleDragOver(source, actor, x, y, time) { handleDragOver(source, actor, x, y, time) {
let app = getAppFromSource(source); let app = getAppFromSource(source);
@@ -865,7 +888,7 @@ var Dash = class Dash {
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
return DND.DragMotionResult.COPY_DROP; return DND.DragMotionResult.COPY_DROP;
} },
// Draggable target interface // Draggable target interface
acceptDrop(source, actor, x, y, time) { acceptDrop(source, actor, x, y, time) {
@@ -899,7 +922,7 @@ var Dash = class Dash {
favPos++; favPos++;
} }
// No drag placeholder means we don't want to favorite the app // No drag placeholder means we don't wan't to favorite the app
// and we are dragging it to its original position // and we are dragging it to its original position
if (!this._dragPlaceholder) if (!this._dragPlaceholder)
return true; return true;
@@ -915,5 +938,6 @@ var Dash = class Dash {
return true; return true;
} }
}; });
Signals.addSignalMethods(Dash.prototype); Signals.addSignalMethods(Dash.prototype);

View File

@@ -1,17 +1,29 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GLib, GnomeDesktop, const GLib = imports.gi.GLib;
GObject, GWeather, Shell, St } = imports.gi; const Gio = imports.gi.Gio;
const GnomeDesktop = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const GWeather = imports.gi.GWeather;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const Params = imports.misc.params;
const Util = imports.misc.util; const Util = imports.misc.util;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
const Weather = imports.misc.weather; const Weather = imports.misc.weather;
const System = imports.system; const System = imports.system;
const MAX_FORECASTS = 5;
function _isToday(date) { function _isToday(date) {
let now = new Date(); let now = new Date();
return now.getYear() == date.getYear() && return now.getYear() == date.getYear() &&
@@ -19,8 +31,10 @@ function _isToday(date) {
now.getDate() == date.getDate(); now.getDate() == date.getDate();
} }
var TodayButton = class TodayButton { var TodayButton = new Lang.Class({
constructor(calendar) { Name: 'TodayButton',
_init(calendar) {
// Having the ability to go to the current date if the user is already // Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive // on the current date can be confusing. So don't make the button reactive
// until the selected date changes. // until the selected date changes.
@@ -47,9 +61,9 @@ var TodayButton = class TodayButton {
this._calendar.connect('selected-date-changed', (calendar, date) => { this._calendar.connect('selected-date-changed', (calendar, date) => {
// Make the button reactive only if the selected date is not the // Make the button reactive only if the selected date is not the
// current date. // current date.
this.actor.reactive = !_isToday(date); this.actor.reactive = !_isToday(date)
}); });
} },
setDate(date) { setDate(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A')); this._dayLabel.set_text(date.toLocaleFormat('%A'));
@@ -69,10 +83,12 @@ var TodayButton = class TodayButton {
dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y")); dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
this.actor.accessible_name = date.toLocaleFormat(dateFormat); this.actor.accessible_name = date.toLocaleFormat(dateFormat);
} }
}; });
var WorldClocksSection = class WorldClocksSection { var WorldClocksSection = new Lang.Class({
constructor() { Name: 'WorldClocksSection',
_init() {
this._clock = new GnomeDesktop.WallClock(); this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0; this._clockNotifyId = 0;
@@ -102,11 +118,11 @@ var WorldClocksSection = class WorldClocksSection {
this._clockAppMon.watchSetting('world-clocks', this._clockAppMon.watchSetting('world-clocks',
this._clocksChanged.bind(this)); this._clocksChanged.bind(this));
this._sync(); this._sync();
} },
_sync() { _sync() {
this.actor.visible = this._clockAppMon.available; this.actor.visible = this._clockAppMon.available;
} },
_clocksChanged(settings) { _clocksChanged(settings) {
this._grid.destroy_all_children(); this._grid.destroy_all_children();
@@ -118,7 +134,7 @@ var WorldClocksSection = class WorldClocksSection {
if (!clocks[i].location) if (!clocks[i].location)
continue; continue;
let l = world.deserialize(clocks[i].location); let l = world.deserialize(clocks[i].location);
if (l && l.get_timezone() != null) if (l)
this._locations.push({ location: l }); this._locations.push({ location: l });
} }
@@ -136,37 +152,26 @@ var WorldClocksSection = class WorldClocksSection {
layout.attach(header, 0, 0, 2, 1); layout.attach(header, 0, 0, 2, 1);
this.actor.label_actor = header; this.actor.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
for (let i = 0; i < this._locations.length; i++) { for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location; let l = this._locations[i].location;
let name = l.get_city_name() || l.get_name(); let name = l.get_level() == GWeather.LocationLevel.NAMED_TIMEZONE ? l.get_name()
: l.get_city_name();
let label = new St.Label({ style_class: 'world-clocks-city', let label = new St.Label({ style_class: 'world-clocks-city',
text: name, text: name,
x_align: Clutter.ActorAlign.START, x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER,
x_expand: true }); x_expand: true });
let time = new St.Label({ style_class: 'world-clocks-time' }); let time = new St.Label({ style_class: 'world-clocks-time',
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
let fmt = (Math.trunc(offset) == offset) ? '%s%.0f' : '%s%.1f';
let prefix = (offset >= 0) ? '+' : '-';
let tz = new St.Label({ style_class: 'world-clocks-timezone',
text: fmt.format(prefix, Math.abs(offset)),
x_align: Clutter.ActorAlign.END, x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER }); x_expand: true });
if (this._grid.text_direction == Clutter.TextDirection.RTL) { if (this._grid.text_direction == Clutter.TextDirection.RTL) {
layout.attach(tz, 0, i + 1, 1, 1); layout.attach(time, 0, i + 1, 1, 1);
layout.attach(time, 1, i + 1, 1, 1); layout.attach(label, 1, i + 1, 1, 1);
layout.attach(label, 2, i + 1, 1, 1);
} else { } else {
layout.attach(label, 0, i + 1, 1, 1); layout.attach(label, 0, i + 1, 1, 1);
layout.attach(time, 1, i + 1, 1, 1); layout.attach(time, 1, i + 1, 1, 1);
layout.attach(tz, 2, i + 1, 1, 1);
} }
this._locations[i].actor = time; this._locations[i].actor = time;
@@ -182,24 +187,22 @@ var WorldClocksSection = class WorldClocksSection {
this._clock.disconnect(this._clockNotifyId); this._clock.disconnect(this._clockNotifyId);
this._clockNotifyId = 0; this._clockNotifyId = 0;
} }
} },
_getTimeAtLocation(location) {
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
return GLib.DateTime.new_now(tz);
}
_updateLabels() { _updateLabels() {
for (let i = 0; i < this._locations.length; i++) { for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i]; let l = this._locations[i];
let now = this._getTimeAtLocation(l.location); let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
let now = GLib.DateTime.new_now(tz);
l.actor.text = Util.formatTime(now, { timeOnly: true }); l.actor.text = Util.formatTime(now, { timeOnly: true });
} }
} }
}; });
var WeatherSection = class WeatherSection { var WeatherSection = new Lang.Class({
constructor() { Name: 'WeatherSection',
_init() {
this._weatherClient = new Weather.WeatherClient(); this._weatherClient = new Weather.WeatherClient();
this.actor = new St.Button({ style_class: 'weather-button', this.actor = new St.Button({ style_class: 'weather-button',
@@ -221,115 +224,111 @@ var WeatherSection = class WeatherSection {
this.actor.child = box; this.actor.child = box;
let titleBox = new St.BoxLayout(); box.add_child(new St.Label({ style_class: 'weather-header',
titleBox.add_child(new St.Label({ style_class: 'weather-header',
x_align: Clutter.ActorAlign.START, x_align: Clutter.ActorAlign.START,
x_expand: true,
text: _("Weather") })); text: _("Weather") }));
box.add_child(titleBox);
this._titleLocation = new St.Label({ style_class: 'weather-header location', this._conditionsLabel = new St.Label({ style_class: 'weather-conditions',
x_align: Clutter.ActorAlign.END }); x_align: Clutter.ActorAlign.START });
titleBox.add_child(this._titleLocation); this._conditionsLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._conditionsLabel.clutter_text.line_wrap = true;
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL }); box.add_child(this._conditionsLabel);
this._forecastGrid = new St.Widget({ style_class: 'weather-grid',
layout_manager: layout });
layout.hookup_style(this._forecastGrid);
box.add_child(this._forecastGrid);
this._weatherClient.connect('changed', this._sync.bind(this)); this._weatherClient.connect('changed', this._sync.bind(this));
this._sync(); this._sync();
} },
_getInfos() { _getSummary(info, capitalize=false) {
let options = capitalize ? GWeather.FormatOptions.SENTENCE_CAPITALIZATION
: GWeather.FormatOptions.NO_CAPITALIZATION;
let [ok, phenomenon, qualifier] = info.get_value_conditions();
if (ok)
return new GWeather.Conditions({ significant: true,
phenomenon,
qualifier }).to_string_full(options);
let [, sky] = info.get_value_sky();
return GWeather.Sky.to_string_full(sky, options);
},
_sameSummary(info1, info2) {
let [ok1, phenom1, qualifier1] = info1.get_value_conditions();
let [ok2, phenom2, qualifier2] = info2.get_value_conditions();
if (ok1 || ok2)
return ok1 == ok2 && phenom1 == phenom2 && qualifier1 == qualifier2;
let [, sky1] = info1.get_value_sky();
let [, sky2] = info2.get_value_sky();
return sky1 == sky2;
},
_getSummaryText() {
let info = this._weatherClient.info; let info = this._weatherClient.info;
let forecasts = info.get_forecast_list(); let forecasts = info.get_forecast_list();
if (forecasts.length == 0) // No forecasts, just current conditions
return '%s.'.format(this._getSummary(info, true));
let current = info; let current = info;
let infos = [info]; let infos = [info];
for (let i = 0; i < forecasts.length; i++) { for (let i = 0; i < forecasts.length; i++) {
let [ok, timestamp] = forecasts[i].get_value_update(); let [ok, timestamp] = forecasts[i].get_value_update();
let datetime = new Date(timestamp * 1000); if (!_isToday(new Date(timestamp * 1000)))
if (!_isToday(datetime))
continue; // Ignore forecasts from other days continue; // Ignore forecasts from other days
[ok, timestamp] = current.get_value_update(); if (this._sameSummary(current, forecasts[i]))
let currenttime = new Date(timestamp * 1000); continue; // Ignore consecutive runs of equal summaries
if (currenttime.getHours() == datetime.getHours())
continue; // Enforce a minimum interval of 1h
current = forecasts[i]; current = forecasts[i];
if (infos.push(current) == MAX_FORECASTS) if (infos.push(current) == 3)
break; // Use a maximum of five forecasts break; // Use a maximum of three summaries
}
return infos;
} }
_addForecasts() { let fmt;
let layout = this._forecastGrid.layout_manager; switch(infos.length) {
/* Translators: %s is a weather condition like "Clear sky"; see
libgweather for the possible condition strings. If at all
possible, the sentence should match the grammatical case etc. of
the inserted conditions. */
case 1: fmt = _("%s all day."); break;
let infos = this._getInfos(); /* Translators: %s is a weather condition like "Clear sky"; see
if (this._forecastGrid.text_direction == Clutter.TextDirection.RTL) libgweather for the possible condition strings. If at all
infos.reverse(); possible, the sentence should match the grammatical case etc. of
the inserted conditions. */
case 2: fmt = _("%s, then %s later."); break;
let col = 0; /* Translators: %s is a weather condition like "Clear sky"; see
infos.forEach(fc => { libgweather for the possible condition strings. If at all
let [ok, timestamp] = fc.get_value_update(); possible, the sentence should match the grammatical case etc. of
let timeStr = Util.formatTime(new Date(timestamp * 1000), { the inserted conditions. */
timeOnly: true case 3: fmt = _("%s, then %s, followed by %s later."); break;
}
let summaries = infos.map((info, i) => {
let capitalize = i == 0 && fmt.startsWith('%s');
return this._getSummary(info, capitalize);
}); });
return String.prototype.format.apply(fmt, summaries);
},
let icon = new St.Icon({ style_class: 'weather-forecast-icon', _getLabelText() {
icon_name: fc.get_symbolic_icon_name(), if (!this._weatherClient.hasLocation)
x_align: Clutter.ActorAlign.CENTER, return _("Select a location…");
x_expand: true });
let temp = new St.Label({ style_class: 'weather-forecast-temp',
text: fc.get_temp_summary(),
x_align: Clutter.ActorAlign.CENTER });
let time = new St.Label({ style_class: 'weather-forecast-time',
text: timeStr,
x_align: Clutter.ActorAlign.CENTER });
layout.attach(icon, col, 0, 1, 1); if (this._weatherClient.loading)
layout.attach(temp, col, 1, 1, 1); return _("Loading…");
layout.attach(time, col, 2, 1, 1);
col++;
});
}
_setStatusLabel(text) {
let layout = this._forecastGrid.layout_manager;
let label = new St.Label({ text });
layout.attach(label, 0, 0, 1, 1);
}
_updateForecasts() {
this._forecastGrid.destroy_all_children();
if (!this._weatherClient.hasLocation) {
this._setStatusLabel(_("Select a location…"));
return;
}
let info = this._weatherClient.info; let info = this._weatherClient.info;
this._titleLocation.text = info.get_location().get_name(); if (info.is_valid())
return this._getSummaryText() + ' ' +
if (this._weatherClient.loading) { /* Translators: %s is a temperature with unit, e.g. "23℃" */
this._setStatusLabel(_("Loading…")); _("Feels like %s.").format(info.get_apparent());
return;
}
if (info.is_valid()) {
this._addForecasts();
return;
}
if (info.network_error()) if (info.network_error())
this._setStatusLabel(_("Go online for weather information")); return _("Go online for weather information");
else
this._setStatusLabel(_("Weather information is currently unavailable")); return _("Weather information is currently unavailable");
} },
_sync() { _sync() {
this.actor.visible = this._weatherClient.available; this.actor.visible = this._weatherClient.available;
@@ -337,14 +336,14 @@ var WeatherSection = class WeatherSection {
if (!this.actor.visible) if (!this.actor.visible)
return; return;
this._titleLocation.visible = this._weatherClient.hasLocation; this._conditionsLabel.text = this._getLabelText();
this._updateForecasts();
} }
}; });
var MessagesIndicator = class MessagesIndicator { var MessagesIndicator = new Lang.Class({
constructor() { Name: 'MessagesIndicator',
_init() {
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic', this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
icon_size: 16, icon_size: 16,
visible: false, y_expand: true, visible: false, y_expand: true,
@@ -357,60 +356,63 @@ var MessagesIndicator = class MessagesIndicator {
Main.messageTray.connect('queue-changed', this._updateCount.bind(this)); Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
let sources = Main.messageTray.getSources(); let sources = Main.messageTray.getSources();
sources.forEach(source => this._onSourceAdded(null, source)); sources.forEach(source => { this._onSourceAdded(null, source); });
} },
_onSourceAdded(tray, source) { _onSourceAdded(tray, source) {
source.connect('count-updated', this._updateCount.bind(this)); source.connect('count-updated', this._updateCount.bind(this));
this._sources.push(source); this._sources.push(source);
this._updateCount(); this._updateCount();
} },
_onSourceRemoved(tray, source) { _onSourceRemoved(tray, source) {
this._sources.splice(this._sources.indexOf(source), 1); this._sources.splice(this._sources.indexOf(source), 1);
this._updateCount(); this._updateCount();
} },
_updateCount() { _updateCount() {
let count = 0; let count = 0;
this._sources.forEach(source => count += source.unseenCount); this._sources.forEach(source => { count += source.unseenCount; });
count -= Main.messageTray.queueCount; count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0); this.actor.visible = (count > 0);
} }
}; });
var IndicatorPad = new Lang.Class({
Name: 'IndicatorPad',
Extends: St.Widget,
var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget {
_init(actor) { _init(actor) {
this._source = actor; this._source = actor;
this._source.connect('notify::visible', () => this.queue_relayout()); this._source.connect('notify::visible', () => { this.queue_relayout(); });
this._source.connect('notify::size', () => this.queue_relayout()); this.parent();
super._init(); },
}
vfunc_get_preferred_width(forHeight) { vfunc_get_preferred_width(container, forHeight) {
if (this._source.visible) if (this._source.visible)
return this._source.get_preferred_width(forHeight); return this._source.get_preferred_width(forHeight);
return [0, 0]; return [0, 0];
} },
vfunc_get_preferred_height(forWidth) { vfunc_get_preferred_height(container, forWidth) {
if (this._source.visible) if (this._source.visible)
return this._source.get_preferred_height(forWidth); return this._source.get_preferred_height(forWidth);
return [0, 0]; return [0, 0];
} }
}); });
var FreezableBinLayout = GObject.registerClass( var FreezableBinLayout = new Lang.Class({
class FreezableBinLayout extends Clutter.BinLayout { Name: 'FreezableBinLayout',
Extends: Clutter.BinLayout,
_init() { _init() {
super._init(); this.parent();
this._frozen = false; this._frozen = false;
this._savedWidth = [NaN, NaN]; this._savedWidth = [NaN, NaN];
this._savedHeight = [NaN, NaN]; this._savedHeight = [NaN, NaN];
} },
set frozen(v) { set frozen(v) {
if (this._frozen == v) if (this._frozen == v)
@@ -419,22 +421,22 @@ class FreezableBinLayout extends Clutter.BinLayout {
this._frozen = v; this._frozen = v;
if (!this._frozen) if (!this._frozen)
this.layout_changed(); this.layout_changed();
} },
vfunc_get_preferred_width(container, forHeight) { vfunc_get_preferred_width(container, forHeight) {
if (!this._frozen || this._savedWidth.some(isNaN)) if (!this._frozen || this._savedWidth.some(isNaN))
return super.vfunc_get_preferred_width(container, forHeight); return this.parent(container, forHeight);
return this._savedWidth; return this._savedWidth;
} },
vfunc_get_preferred_height(container, forWidth) { vfunc_get_preferred_height(container, forWidth) {
if (!this._frozen || this._savedHeight.some(isNaN)) if (!this._frozen || this._savedHeight.some(isNaN))
return super.vfunc_get_preferred_height(container, forWidth); return this.parent(container, forWidth);
return this._savedHeight; return this._savedHeight;
} },
vfunc_allocate(container, allocation, flags) { vfunc_allocate(container, allocation, flags) {
super.vfunc_allocate(container, allocation, flags); this.parent(container, allocation, flags);
let [width, height] = allocation.get_size(); let [width, height] = allocation.get_size();
this._savedWidth = [width, width]; this._savedWidth = [width, width];
@@ -442,30 +444,35 @@ class FreezableBinLayout extends Clutter.BinLayout {
} }
}); });
var CalendarColumnLayout = GObject.registerClass( var CalendarColumnLayout = new Lang.Class({
class CalendarColumnLayout extends Clutter.BoxLayout { Name: 'CalendarColumnLayout',
Extends: Clutter.BoxLayout,
_init(actor) { _init(actor) {
super._init({ orientation: Clutter.Orientation.VERTICAL }); this.parent({ orientation: Clutter.Orientation.VERTICAL });
this._calActor = actor; this._calActor = actor;
} },
vfunc_get_preferred_width(container, forHeight) { vfunc_get_preferred_width(container, forHeight) {
if (!this._calActor || this._calActor.get_parent() != container) if (!this._calActor || this._calActor.get_parent() != container)
return super.vfunc_get_preferred_width(container, forHeight); return this.parent(container, forHeight);
return this._calActor.get_preferred_width(forHeight); return this._calActor.get_preferred_width(forHeight);
} }
}); });
var DateMenuButton = GObject.registerClass( var DateMenuButton = new Lang.Class({
class DateMenuButton extends PanelMenu.Button { Name: 'DateMenuButton',
Extends: PanelMenu.Button,
_init() { _init() {
let item;
let hbox; let hbox;
let vbox; let vbox;
let menuAlignment = 0.5; let menuAlignment = 0.5;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
menuAlignment = 1.0 - menuAlignment; menuAlignment = 1.0 - menuAlignment;
super._init(menuAlignment); this.parent(menuAlignment);
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER }); this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this._indicator = new MessagesIndicator(); this._indicator = new MessagesIndicator();
@@ -475,9 +482,10 @@ class DateMenuButton extends PanelMenu.Button {
box.add_actor(this._clockDisplay); box.add_actor(this._clockDisplay);
box.add_actor(this._indicator.actor); box.add_actor(this._indicator.actor);
this.label_actor = this._clockDisplay; this.actor.label_actor = this._clockDisplay;
this.add_actor(box); this.actor.add_actor(box);
this.add_style_class_name ('clock-display'); this.actor.add_style_class_name ('clock-display');
let layout = new FreezableBinLayout(); let layout = new FreezableBinLayout();
let bin = new St.Widget({ layout_manager: layout }); let bin = new St.Widget({ layout_manager: layout });
@@ -524,7 +532,7 @@ class DateMenuButton extends PanelMenu.Button {
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade', this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
x_expand: true, x_fill: true, x_expand: true, x_fill: true,
overlay_scrollbars: true }); overlay_scrollbars: true });
this._displaysSection.set_policy(St.PolicyType.NEVER, St.PolicyType.AUTOMATIC); this._displaysSection.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
vbox.add_actor(this._displaysSection); vbox.add_actor(this._displaysSection);
let displaysBox = new St.BoxLayout({ vertical: true, let displaysBox = new St.BoxLayout({ vertical: true,
@@ -545,11 +553,11 @@ class DateMenuButton extends PanelMenu.Button {
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated(); this._sessionUpdated();
} },
_getEventSource() { _getEventSource() {
return new Calendar.DBusEventSource(); return new Calendar.DBusEventSource();
} },
_setEventSource(eventSource) { _setEventSource(eventSource) {
if (this._eventSource) if (this._eventSource)
@@ -559,7 +567,7 @@ class DateMenuButton extends PanelMenu.Button {
this._messageList.setEventSource(eventSource); this._messageList.setEventSource(eventSource);
this._eventSource = eventSource; this._eventSource = eventSource;
} },
_updateTimeZone() { _updateTimeZone() {
// SpiderMonkey caches the time zone so we must explicitly clear it // SpiderMonkey caches the time zone so we must explicitly clear it
@@ -568,7 +576,7 @@ class DateMenuButton extends PanelMenu.Button {
System.clearDateCaches(); System.clearDateCaches();
this._calendar.updateTimeZone(); this._calendar.updateTimeZone();
} },
_sessionUpdated() { _sessionUpdated() {
let eventSource; let eventSource;

View File

@@ -1,11 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GObject, Pango, St } = imports.gi; const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Lang = imports.lang;
var Dialog = new Lang.Class({
Name: 'Dialog',
Extends: St.Widget,
var Dialog = GObject.registerClass(
class Dialog extends St.Widget {
_init(parentActor, styleClass) { _init(parentActor, styleClass) {
super._init({ layout_manager: new Clutter.BinLayout() }); this.parent({ layout_manager: new Clutter.BinLayout() });
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this._initialKeyFocus = null; this._initialKeyFocus = null;
@@ -21,7 +28,7 @@ class Dialog extends St.Widget {
this._parentActor = parentActor; this._parentActor = parentActor;
this._eventId = this._parentActor.connect('event', this._modalEventHandler.bind(this)); this._eventId = this._parentActor.connect('event', this._modalEventHandler.bind(this));
this._parentActor.add_child(this); this._parentActor.add_child(this);
} },
_createDialog() { _createDialog() {
this._dialog = new St.BoxLayout({ style_class: 'modal-dialog', this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
@@ -44,17 +51,17 @@ class Dialog extends St.Widget {
x_align: St.Align.MIDDLE, x_align: St.Align.MIDDLE,
y_align: St.Align.START }); y_align: St.Align.START });
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) }); this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous:true }) });
this._dialog.add(this.buttonLayout, this._dialog.add(this.buttonLayout,
{ x_align: St.Align.MIDDLE, { x_align: St.Align.MIDDLE,
y_align: St.Align.START }); y_align: St.Align.START });
} },
_onDestroy() { _onDestroy() {
if (this._eventId != 0) if (this._eventId != 0)
this._parentActor.disconnect(this._eventId); this._parentActor.disconnect(this._eventId);
this._eventId = 0; this._eventId = 0;
} },
_modalEventHandler(actor, event) { _modalEventHandler(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS) { if (event.type() == Clutter.EventType.KEY_PRESS) {
@@ -80,7 +87,7 @@ class Dialog extends St.Widget {
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} },
_setInitialKeyFocus(actor) { _setInitialKeyFocus(actor) {
if (this._initialKeyFocus) if (this._initialKeyFocus)
@@ -92,15 +99,15 @@ class Dialog extends St.Widget {
this._initialKeyFocus = null; this._initialKeyFocus = null;
this._initialKeyFocusDestroyId = 0; this._initialKeyFocusDestroyId = 0;
}); });
} },
get initialKeyFocus() { get initialKeyFocus() {
return this._initialKeyFocus || this; return this._initialKeyFocus || this;
} },
addContent(actor) { addContent(actor) {
this.contentLayout.add (actor, { expand: true }); this.contentLayout.add (actor, { expand: true });
} },
addButton(buttonInfo) { addButton(buttonInfo) {
let { label, action, key } = buttonInfo; let { label, action, key } = buttonInfo;
@@ -137,15 +144,17 @@ class Dialog extends St.Widget {
this.buttonLayout.add_actor(button); this.buttonLayout.add_actor(button);
return button; return button;
} },
clearButtons() { clearButtons() {
this.buttonLayout.destroy_all_children(); this.buttonLayout.destroy_all_children();
this._buttonKeys = {}; this._buttonKeys = {};
} },
}); });
var MessageDialogContent = GObject.registerClass({ var MessageDialogContent = new Lang.Class({
Name: 'MessageDialogContent',
Extends: St.BoxLayout,
Properties: { Properties: {
'icon': GObject.ParamSpec.object('icon', 'icon', 'icon', 'icon': GObject.ParamSpec.object('icon', 'icon', 'icon',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.READWRITE |
@@ -163,8 +172,8 @@ var MessageDialogContent = GObject.registerClass({
GObject.ParamFlags.READWRITE | GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT, GObject.ParamFlags.CONSTRUCT,
null) null)
} },
}, class MessageDialogContent extends St.BoxLayout {
_init(params) { _init(params) {
this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START }); this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
this._title = new St.Label({ style_class: 'headline' }); this._title = new St.Label({ style_class: 'headline' });
@@ -175,15 +184,15 @@ var MessageDialogContent = GObject.registerClass({
this[`_${prop}`].add_style_class_name(`message-dialog-${prop}`); this[`_${prop}`].add_style_class_name(`message-dialog-${prop}`);
}); });
let textProps = { ellipsize: Pango.EllipsizeMode.NONE, let textProps = { ellipsize_mode: Pango.EllipsizeMode.NONE,
line_wrap: true }; line_wrap: true };
this._subtitle.clutter_text.set(textProps); Object.assign(this._subtitle.clutter_text, textProps);
this._body.clutter_text.set(textProps); Object.assign(this._body.clutter_text, textProps);
if (!params.hasOwnProperty('style_class')) if (!params.hasOwnProperty('style_class'))
params.style_class = 'message-dialog-main-layout'; params.style_class = 'message-dialog-main-layout';
super._init(params); this.parent(params);
this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content', this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content',
x_expand: true, x_expand: true,
@@ -195,51 +204,45 @@ var MessageDialogContent = GObject.registerClass({
this.add_actor(this._icon); this.add_actor(this._icon);
this.add_actor(this.messageBox); this.add_actor(this.messageBox);
} },
get icon() { get icon() {
return this._icon.gicon; return this._icon.gicon;
} },
get title() { get title() {
return this._title.text; return this._title.text;
} },
get subtitle() { get subtitle() {
return this._subtitle.text; return this._subtitle.text;
} },
get body() { get body() {
return this._body.text; return this._body.text;
} },
set icon(icon) { set icon(icon) {
this._icon.set({ Object.assign(this._icon, { gicon: icon, visible: icon != null });
gicon: icon,
visible: icon != null
});
this.notify('icon'); this.notify('icon');
} },
set title(title) { set title(title) {
this._setLabel(this._title, 'title', title); this._setLabel(this._title, 'title', title);
} },
set subtitle(subtitle) { set subtitle(subtitle) {
this._setLabel(this._subtitle, 'subtitle', subtitle); this._setLabel(this._subtitle, 'subtitle', subtitle);
} },
set body(body) { set body(body) {
this._setLabel(this._body, 'body', body); this._setLabel(this._body, 'body', body);
} },
_setLabel(label, prop, value) { _setLabel(label, prop, value) {
label.set({ Object.assign(label, { text: value || '', visible: value != null });
text: value || '',
visible: value != null
});
this.notify(prop); this.notify(prop);
} },
insertBeforeBody(actor) { insertBeforeBody(actor) {
this.messageBox.insert_child_below(actor, this._body); this.messageBox.insert_child_below(actor, this._body);

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